1 /* CONSOLE.C    (c)Copyright Roger Bowler, 1999-2011                 */
2 /*              Hercules Console Device Handler                      */
3 
4 /*-------------------------------------------------------------------*/
5 /* This module contains device handling functions for console        */
6 /* devices for the Hercules ESA/390 emulator.                        */
7 /*                                                                   */
8 /* Telnet support is provided for two classes of console device:     */
9 /* - local non-SNA 3270 display consoles via tn3270                  */
10 /* - local non-SNA 3270 printers         via tn3270                  */
11 /* - 1052 and 3215 console printer keyboards via regular telnet      */
12 /*-------------------------------------------------------------------*/
13 
14 /*-------------------------------------------------------------------*/
15 /* This module also takes care of the differences between the        */
16 /* remote 3270 and local non-SNA 3270 devices.  In particular        */
17 /* the support of command chaining, which is not supported on        */
18 /* the remote 3270 implementation on which telnet 3270 is based.     */
19 /* In the local non-SNA environment a chained read or write will     */
20 /* continue at the buffer address where the previous command ended.  */
21 /* In order to achieve this, this module will keep track of the      */
22 /* buffer location, and adjust the buffer address on chained read    */
23 /* and write operations.                                             */
24 /*                                           03/06/00 Jan Jaeger.    */
25 /*-------------------------------------------------------------------*/
26 
27 /*-------------------------------------------------------------------*/
28 /* Add code to bypass bug in telnet client from TCP/IP for OS/390    */
29 /* where telnet responds with the server response rather then the    */
30 /* client response as documented in RFC1576.                         */
31 /*                                           20/06/00 Jan Jaeger.    */
32 /*-------------------------------------------------------------------*/
33 
34 /*-------------------------------------------------------------------*/
35 /* Corrections to buffer position calculations in find_buffer_pos    */
36 /* and get_screen_pos subroutines (symptom: message IEE305I)         */
37 /*                                           09/12/00 Roger Bowler.  */
38 /*-------------------------------------------------------------------*/
39 
40 /*-------------------------------------------------------------------*/
41 /* When using VTAM with local non-SNA 3270 devices, ensure that      */
42 /* enough bufferspace is available when doing IND$FILE type          */
43 /* filetransfers.  Code IOBUF=(,3992) in ATCSTRxx, and/or BUFNUM=xxx */
44 /* on the LBUILD LOCAL statement defining the 3270 device.    JJ     */
45 /*                                                                   */
46 /*-------------------------------------------------------------------*/
47 
48 /*-------------------------------------------------------------------*/
49 /* Ignore "Negotiate About Window Size" client option (for now) so   */
50 /* WinNT version of telnet works. -- Greg Price (implemted by Fish)  */
51 /*-------------------------------------------------------------------*/
52 
53 #include "hstdinc.h"
54 #include "hercules.h"
55 
56 #include "devtype.h"
57 
58 #include "opcode.h"
59 
60 #include "sr.h"
61 
62 #if defined(WIN32) && defined(OPTION_DYNAMIC_LOAD) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
63   SYSBLK *psysblk;
64   #define sysblk (*psysblk)
65   #define config_cnslport (*config_cnslport)
66   static
67 #else
68  #if defined(OPTION_DYNAMIC_LOAD) && defined(_MSVC_)
69   DLL_IMPORT
70  #else
71   extern
72  #endif
73 #endif
74 char *config_cnslport;
75 
76 /*-------------------------------------------------------------------*/
77 /* Ivan Warren 20040227                                              */
78 /* This table is used by channel.c to determine if a CCW code is an  */
79 /* immediate command or not                                          */
80 /* The tape is addressed in the DEVHND structure as 'DEVIMM immed'   */
81 /* 0 : Command is NOT an immediate command                           */
82 /* 1 : Command is an immediate command                               */
83 /* Note : An immediate command is defined as a command which returns */
84 /* CE (channel end) during initialisation (that is, no data is       */
85 /* actually transfered. In this case, IL is not indicated for a CCW  */
86 /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in     */
87 /* effect                                                            */
88 /*-------------------------------------------------------------------*/
89 static BYTE constty_immed[256]=
90  /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
91   { 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,  /* 00 */
92     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 10 */
93     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 20 */
94     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 30 */
95     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 40 */
96     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 50 */
97     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 60 */
98     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 70 */
99     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 80 */
100     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 90 */
101     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* A0 */
102     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* B0 */
103     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* C0 */
104     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* D0 */
105     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* E0 */
106     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* F0 */
107 
108 static BYTE loc3270_immed[256]=
109  /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
110   { 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,  /* 00 */
111     0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,  /* 10 */
112     0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,  /* 20 */
113     0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,  /* 30 */
114     0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,  /* 40 */
115     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 50 */
116     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 60 */
117     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 70 */
118     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 80 */
119     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 90 */
120     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* A0 */
121     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* B0 */
122     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* C0 */
123     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* D0 */
124     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* E0 */
125     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* F0 */
126 /*-------------------------------------------------------------------*/
127 /* Telnet command definitions                                        */
128 /*-------------------------------------------------------------------*/
129 #define BINARY          0       /* Binary Transmission */
130 #define IS              0       /* Used by terminal-type negotiation */
131 #define SEND            1       /* Used by terminal-type negotiation */
132 #define ECHO_OPTION     1       /* Echo option */
133 #define SUPPRESS_GA     3       /* Suppress go-ahead option */
134 #define TIMING_MARK     6       /* Timing mark option */
135 #define TERMINAL_TYPE   24      /* Terminal type option */
136 #define NAWS            31      /* Negotiate About Window Size */
137 #define EOR             25      /* End of record option */
138 #define EOR_MARK        239     /* End of record marker */
139 #define SE              240     /* End of subnegotiation parameters */
140 #define NOP             241     /* No operation */
141 #define DATA_MARK       242     /* The data stream portion of a Synch.
142                                    This should always be accompanied
143                                    by a TCP Urgent notification */
144 #define BRK             243     /* Break character */
145 #define IP              244     /* Interrupt Process */
146 #define AO              245     /* Abort Output */
147 #define AYT             246     /* Are You There */
148 #define EC              247     /* Erase character */
149 #define EL              248     /* Erase Line */
150 #define GA              249     /* Go ahead */
151 #define SB              250     /* Subnegotiation of indicated option */
152 #define WILL            251     /* Indicates the desire to begin
153                                    performing, or confirmation that
154                                    you are now performing, the
155                                    indicated option */
156 #define WONT            252     /* Indicates the refusal to perform,
157                                    or continue performing, the
158                                    indicated option */
159 #define DO              253     /* Indicates the request that the
160                                    other party perform, or
161                                    confirmation that you are expecting
162                                    the other party to perform, the
163                                    indicated option */
164 #define DONT            254     /* Indicates the demand that the
165                                    other party stop performing,
166                                    or confirmation that you are no
167                                    longer expecting the other party
168                                    to perform, the indicated option */
169 #define IAC             255     /* Interpret as Command */
170 
171 /*-------------------------------------------------------------------*/
172 /* 3270 definitions                                                  */
173 /*-------------------------------------------------------------------*/
174 
175 /* 3270 local commands (CCWs) */
176 #define L3270_EAU       0x0F            /* Erase All Unprotected     */
177 #define L3270_EW        0x05            /* Erase/Write               */
178 #define L3270_EWA       0x0D            /* Erase/Write Alternate     */
179 #define L3270_RB        0x02            /* Read Buffer               */
180 #define L3270_RM        0x06            /* Read Modified             */
181 #define L3270_WRT       0x01            /* Write                     */
182 #define L3270_WSF       0x11            /* Write Structured Field    */
183 
184 #define L3270_NOP       0x03            /* No Operation              */
185 #define L3270_SELRM     0x0B            /* Select RM                 */
186 #define L3270_SELRB     0x1B            /* Select RB                 */
187 #define L3270_SELRMP    0x2B            /* Select RMP                */
188 #define L3270_SELRBP    0x3B            /* Select RBP                */
189 #define L3270_SELWRT    0x4B            /* Select WRT                */
190 #define L3270_SENSE     0x04            /* Sense                     */
191 #define L3270_SENSEID   0xE4            /* Sense ID                  */
192 
193 /* 3270 remote commands */
194 #define R3270_EAU       0x6F            /* Erase All Unprotected     */
195 #define R3270_EW        0xF5            /* Erase/Write               */
196 #define R3270_EWA       0x7E            /* Erase/Write Alternate     */
197 #define R3270_RB        0xF2            /* Read Buffer               */
198 #define R3270_RM        0xF6            /* Read Modified             */
199 #define R3270_RMA       0x6E            /* Read Modified All         */
200 #define R3270_WRT       0xF1            /* Write                     */
201 #define R3270_WSF       0xF3            /* Write Structured Field    */
202 
203 /* 3270 orders */
204 #define O3270_SBA       0x11            /* Set Buffer Address        */
205 #define O3270_SF        0x1D            /* Start Field               */
206 #define O3270_SFE       0x29            /* Start Field Extended      */
207 #define O3270_SA        0x28            /* Set Attribute             */
208 #define O3270_IC        0x13            /* Insert Cursor             */
209 #define O3270_MF        0x2C            /* Modify Field              */
210 #define O3270_PT        0x05            /* Program Tab               */
211 #define O3270_RA        0x3C            /* Repeat to Address         */
212 #define O3270_EUA       0x12            /* Erase Unprotected to Addr */
213 #define O3270_GE        0x08            /* Graphic Escape            */
214 
215 /* Inbound structured fields */
216 #define SF3270_AID      0x88            /* Aid value of inbound SF   */
217 #define SF3270_3270DS   0x80            /* SFID of 3270 datastream SF*/
218 
219 /* 12 bit 3270 buffer address code conversion table                  */
220 static BYTE sba_code[] = { "\x40\xC1\xC2\xC3\xC4\xC5\xC6\xC7"
221                            "\xC8\xC9\x4A\x4B\x4C\x4D\x4E\x4F"
222                            "\x50\xD1\xD2\xD3\xD4\xD5\xD6\xD7"
223                            "\xD8\xD9\x5A\x5B\x5C\x5D\x5E\x5F"
224                            "\x60\x61\xE2\xE3\xE4\xE5\xE6\xE7"
225                            "\xE8\xE9\x6A\x6B\x6C\x6D\x6E\x6F"
226                            "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7"
227                            "\xF8\xF9\x7A\x7B\x7C\x7D\x7E\x7F" };
228 
229 /*-------------------------------------------------------------------*/
230 /* Internal macro definitions                                        */
231 /*-------------------------------------------------------------------*/
232 
233 /* DEBUG_LVL: 0 = none
234               1 = status
235               2 = headers
236               3 = buffers
237 */
238 #define DEBUG_LVL        0
239 
240 #if DEBUG_LVL == 0
241   #define TNSDEBUG1      1 ? ((void)0) : logmsg
242   #define TNSDEBUG2      1 ? ((void)0) : logmsg
243   #define TNSDEBUG3      1 ? ((void)0) : logmsg
244 #endif
245 #if DEBUG_LVL == 1
246   #define TNSDEBUG1      logmsg
247   #define TNSDEBUG2      1 ? ((void)0) : logmsg
248   #define TNSDEBUG3      1 ? ((void)0) : logmsg
249 #endif
250 #if DEBUG_LVL == 2
251   #define TNSDEBUG1      logmsg
252   #define TNSDEBUG2      logmsg
253   #define TNSDEBUG3      1 ? ((void)0) : logmsg
254 #endif
255 #if DEBUG_LVL == 3
256   #define TNSDEBUG1      logmsg
257   #define TNSDEBUG2      logmsg
258   #define TNSDEBUG3      logmsg
259 #endif
260 
261 #define TNSERROR        logmsg
262 
263 #define BUFLEN_3270     65536           /* 3270 Send/Receive buffer  */
264 #define BUFLEN_1052     150             /* 1052 Send/Receive buffer  */
265 
266 
267 #undef  FIX_QWS_BUG_FOR_MCS_CONSOLES
268 
269 /*-------------------------------------------------------------------*/
270 /* Static data areas                                                 */
271 /*-------------------------------------------------------------------*/
272 static  HOST_INFO  cons_hostinfo;       /* Host info for this system */
273 
274 
275 /*-------------------------------------------------------------------*/
276 /* SUBROUTINE TO TRACE THE CONTENTS OF AN ASCII MESSAGE PACKET       */
277 /*-------------------------------------------------------------------*/
278 #if DEBUG_LVL == 3
279 static void
packet_trace(BYTE * addr,int len)280 packet_trace(BYTE *addr, int len)
281 {
282 int  i, offset;
283 BYTE c;
284 BYTE print_chars[17];
285 
286     for (offset=0; offset < len; )
287     {
288         memset(print_chars,0,sizeof(print_chars));
289         logmsg("+%4.4X  ", offset);
290         for (i=0; i < 16; i++)
291         {
292             c = *addr++;
293             if (offset < len) {
294                 logmsg("%2.2X", c);
295                 print_chars[i] = '.';
296                 if (isprint(c)) print_chars[i] = c;
297                 c = guest_to_host(c);
298                 if (isprint(c)) print_chars[i] = c;
299             }
300             else {
301                 logmsg("  ");
302             }
303             offset++;
304             if ((offset & 3) == 0) {
305                 logmsg(" ");
306             }
307         } /* end for(i) */
308         logmsg(" %s\n", print_chars);
309     } /* end for(offset) */
310 
311 } /* end function packet_trace */
312 #else
313  #define packet_trace( _addr, _len)
314 #endif
315 
316 
317 #if 1
get_inet_socket(char * host_serv)318 struct sockaddr_in * get_inet_socket(char *host_serv)
319 {
320 char *host = NULL;
321 char *serv;
322 struct sockaddr_in *sin;
323 
324     if((serv = strchr(host_serv,':')))
325     {
326         *serv++ = '\0';
327         if(*host_serv)
328             host = host_serv;
329     }
330     else
331         serv = host_serv;
332 
333     if(!(sin = malloc(sizeof(struct sockaddr_in))))
334         return sin;
335 
336     sin->sin_family = AF_INET;
337 
338     if(host)
339     {
340     struct hostent *hostent;
341 
342         hostent = gethostbyname(host);
343 
344         if(!hostent)
345         {
346             logmsg(_("HHCGI001I Unable to determine IP address from %s\n"),
347                 host);
348             free(sin);
349             return NULL;
350         }
351 
352         memcpy(&sin->sin_addr,*hostent->h_addr_list,sizeof(sin->sin_addr));
353     }
354     else
355         sin->sin_addr.s_addr = INADDR_ANY;
356 
357     if(serv)
358     {
359         if(!isdigit(*serv))
360         {
361         struct servent *servent;
362 
363             servent = getservbyname(serv, "tcp");
364 
365             if(!servent)
366             {
367                 logmsg(_("HHCGI002I Unable to determine port number from %s\n"),
368                     host);
369                 free(sin);
370                 return NULL;
371             }
372 
373             sin->sin_port = servent->s_port;
374         }
375         else
376             sin->sin_port = htons(atoi(serv));
377 
378     }
379     else
380     {
381         logmsg(_("HHCGI003E Invalid parameter: %s\n"),
382             host_serv);
383         free(sin);
384         return NULL;
385     }
386 
387     return sin;
388 
389 }
390 
391 #endif
392 /*-------------------------------------------------------------------*/
393 /* SUBROUTINE TO REMOVE ANY IAC SEQUENCES FROM THE DATA STREAM       */
394 /* Returns the new length after deleting IAC commands                */
395 /*-------------------------------------------------------------------*/
396 static int
remove_iac(BYTE * buf,int len)397 remove_iac (BYTE *buf, int len)
398 {
399 int     m, n, c;
400 
401     for (m=0, n=0; m < len; ) {
402         /* Interpret IAC commands */
403         if (buf[m] == IAC) {
404             /* Treat IAC in last byte of buffer as IAC NOP */
405             c = (++m < len)? buf[m++] : NOP;
406             /* Process IAC command */
407             switch (c) {
408             case IAC: /* Insert single IAC in buffer */
409                 buf[n++] = IAC;
410                 break;
411             case BRK: /* Set ATTN indicator */
412                 break;
413             case IP: /* Set SYSREQ indicator */
414                 break;
415             case WILL: /* Skip option negotiation command */
416             case WONT:
417             case DO:
418             case DONT:
419                 m++;
420                 break;
421             case SB: /* Skip until IAC SE sequence found */
422                 for (; m < len; m++) {
423                     if (buf[m] != IAC) continue;
424                     if (++m >= len) break;
425                     if (buf[m] == SE) { m++; break; }
426                 } /* end for */
427             default: /* Ignore NOP or unknown command */
428                 break;
429             } /* end switch(c) */
430         } else {
431             /* Copy data bytes */
432             if (n < m) buf[n] = buf[m];
433             m++; n++;
434         }
435     } /* end for */
436 
437     if (n < m) {
438         TNSDEBUG3("console: DBG001: %d IAC bytes removed, newlen=%d\n",
439                 m-n, n);
440         packet_trace (buf, n);
441     }
442 
443     return n;
444 
445 } /* end function remove_iac */
446 
447 
448 /*-------------------------------------------------------------------*/
449 /* SUBROUTINE TO DOUBLE UP ANY IAC BYTES IN THE DATA STREAM          */
450 /* Returns the new length after inserting extra IAC bytes            */
451 /*-------------------------------------------------------------------*/
452 static int
double_up_iac(BYTE * buf,int len)453 double_up_iac (BYTE *buf, int len)
454 {
455 int     m, n, x, newlen;
456 
457     /* Count the number of IAC bytes in the data */
458     for (x=0, n=0; n < len; n++)
459         if (buf[n] == IAC) x++;
460 
461     /* Exit if nothing to do */
462     if (x == 0) return len;
463 
464     /* Insert extra IAC bytes backwards from the end of the buffer */
465     newlen = len + x;
466     TNSDEBUG3("console: DBG002: %d IAC bytes added, newlen=%d\n",
467             x, newlen);
468     for (n=newlen, m=len; n > m; ) {
469         buf[--n] = buf[--m];
470         if (buf[n] == IAC) buf[--n] = IAC;
471     }
472     packet_trace (buf, newlen);
473     return newlen;
474 
475 } /* end function double_up_iac */
476 
477 
478 /*-------------------------------------------------------------------*/
479 /* SUBROUTINE TO TRANSLATE A NULL-TERMINATED STRING TO EBCDIC        */
480 /*-------------------------------------------------------------------*/
481 static BYTE *
translate_to_ebcdic(char * str)482 translate_to_ebcdic (char *str)
483 {
484 int     i;                              /* Array subscript           */
485 BYTE    c;                              /* Character work area       */
486 
487     for (i = 0; str[i] != '\0'; i++)
488     {
489         c = str[i];
490         str[i] = (isprint(c) ? host_to_guest(c) : SPACE);
491     }
492 
493     return (BYTE *)str;
494 } /* end function translate_to_ebcdic */
495 
496 
497 /*-------------------------------------------------------------------*/
498 /* SUBROUTINE TO SEND A DATA PACKET TO THE CLIENT                    */
499 /*-------------------------------------------------------------------*/
500 static int
send_packet(int csock,BYTE * buf,int len,char * caption)501 send_packet (int csock, BYTE *buf, int len, char *caption)
502 {
503 int     rc;                             /* Return code               */
504 
505     if (caption != NULL) {
506         TNSDEBUG2("console: DBG003: Sending %s\n", caption);
507         packet_trace (buf, len);
508     }
509 
510     rc = send (csock, buf, len, 0);
511 
512     if (rc < 0) {
513         TNSERROR("console: DBG021: send: %s\n", strerror(HSO_errno));
514         return -1;
515     } /* end if(rc) */
516 
517     return 0;
518 
519 } /* end function send_packet */
520 
521 
522 /*-------------------------------------------------------------------*/
523 /* SUBROUTINE TO RECEIVE A DATA PACKET FROM THE CLIENT               */
524 /* This subroutine receives bytes from the client.  It stops when    */
525 /* the receive buffer is full, or when the last two bytes received   */
526 /* consist of the IAC character followed by a specified delimiter.   */
527 /* If zero bytes are received, this means the client has closed the  */
528 /* connection, and this is treated as an error.                      */
529 /* Input:                                                            */
530 /*      csock is the socket number                                   */
531 /*      buf points to area to receive data                           */
532 /*      reqlen is the number of bytes requested                      */
533 /*      delim is the delimiter character (0=no delimiter)            */
534 /* Output:                                                           */
535 /*      buf is updated with data received                            */
536 /*      The return value is the number of bytes received, or         */
537 /*      -1 if an error occurred.                                     */
538 /*-------------------------------------------------------------------*/
539 static int
recv_packet(int csock,BYTE * buf,int reqlen,BYTE delim)540 recv_packet (int csock, BYTE *buf, int reqlen, BYTE delim)
541 {
542 int     rc=0;                           /* Return code               */
543 int     rcvlen=0;                       /* Length of data received   */
544 
545     while (rcvlen < reqlen) {
546 
547         rc = recv (csock, buf + rcvlen, reqlen - rcvlen, 0);
548 
549         if (rc < 0) {
550             TNSERROR("console: DBG022: recv: %s\n", strerror(HSO_errno));
551             return -1;
552         }
553 
554         if (rc == 0) {
555             TNSDEBUG1("console: DBG004: Connection closed by client\n");
556             return -1;
557         }
558 
559         rcvlen += rc;
560 
561         if (delim != '\0' && rcvlen >= 2
562             && buf[rcvlen-2] == IAC && buf[rcvlen-1] == delim)
563             break;
564     }
565 
566     TNSDEBUG2("console: DBG005: Packet received length=%d\n", rcvlen);
567     packet_trace (buf, rcvlen);
568 
569     return rcvlen;
570 
571 } /* end function recv_packet */
572 
573 
574 /*-------------------------------------------------------------------*/
575 /* SUBROUTINE TO RECEIVE A PACKET AND COMPARE WITH EXPECTED VALUE    */
576 /*-------------------------------------------------------------------*/
577 static int
expect(int csock,BYTE * expected,int len,char * caption)578 expect (int csock, BYTE *expected, int len, char *caption)
579 {
580 int     rc;                             /* Return code               */
581 BYTE    buf[512];                       /* Receive buffer            */
582 #if 1
583 /* TCP/IP for MVS returns the server sequence rather then
584    the client sequence during bin negotiation    19/06/00 Jan Jaeger */
585 static BYTE do_bin[] = { IAC, DO, BINARY, IAC, WILL, BINARY };
586 static BYTE will_bin[] = { IAC, WILL, BINARY, IAC, DO, BINARY };
587 #endif
588 
589     UNREFERENCED(caption);
590 
591     rc = recv_packet (csock, buf, len, 0);
592     if (rc < 0) return -1;
593 
594 #if 1
595         /* TCP/IP FOR MVS DOES NOT COMPLY TO RFC 1576 THIS IS A BYPASS */
596         if(memcmp(buf, expected, len) != 0
597           && !(len == sizeof(will_bin)
598               && memcmp(expected, will_bin, len) == 0
599               && memcmp(buf, do_bin, len) == 0) )
600 #else
601     if (memcmp(buf, expected, len) != 0)
602 #endif
603     {
604         TNSDEBUG2("console: DBG006: Expected %s\n", caption);
605         return -1;
606     }
607     TNSDEBUG2("console: DBG007: Received %s\n", caption);
608 
609     return 0;
610 
611 } /* end function expect */
612 
613 
614 /*-------------------------------------------------------------------*/
615 /* SUBROUTINE TO NEGOTIATE TELNET PARAMETERS                         */
616 /* This subroutine negotiates the terminal type with the client      */
617 /* and uses the terminal type to determine whether the client        */
618 /* is to be supported as a 3270 display console or as a 1052/3215    */
619 /* printer-keyboard console.                                         */
620 /*                                                                   */
621 /* Valid display terminal types are "IBM-NNNN", "IBM-NNNN-M", and    */
622 /* "IBM-NNNN-M-E", where NNNN is 3270, 3277, 3278, 3279, 3178, 3179, */
623 /* or 3180, M indicates the screen size (2=25x80, 3=32x80, 4=43x80,  */
624 /* 5=27x132, X=determined by Read Partition Query command), and      */
625 /* -E is an optional suffix indicating that the terminal supports    */
626 /* extended attributes. Displays are negotiated into tn3270 mode.    */
627 /* An optional device number suffix (example: IBM-3270@01F) may      */
628 /* be specified to request allocation to a specific device number.   */
629 /* Valid 3270 printer type is "IBM-3287-1"                           */
630 /*                                                                   */
631 /* Terminal types whose first four characters are not "IBM-" are     */
632 /* handled as printer-keyboard consoles using telnet line mode.      */
633 /*                                                                   */
634 /* Input:                                                            */
635 /*      csock   Socket number for client connection                  */
636 /* Output:                                                           */
637 /*      class   D=3270 display console, K=printer-keyboard console   */
638 /*              P=3270 printer                                       */
639 /*      model   3270 model indicator (2,3,4,5,X)                     */
640 /*      extatr  3270 extended attributes (Y,N)                       */
641 /*      devn    Requested device number, or FFFF=any device number   */
642 /* Return value:                                                     */
643 /*      0=negotiation successful, -1=negotiation error               */
644 /*-------------------------------------------------------------------*/
645 static int
negotiate(int csock,BYTE * class,BYTE * model,BYTE * extatr,U16 * devn,char * group)646 negotiate(int csock, BYTE *class, BYTE *model, BYTE *extatr, U16 *devn,char *group)
647 {
648 int    rc;                              /* Return code               */
649 char  *termtype;                        /* Pointer to terminal type  */
650 char  *s;                               /* String pointer            */
651 BYTE   c;                               /* Trailing character        */
652 U16    devnum;                          /* Requested device number   */
653 BYTE   buf[512];                        /* Telnet negotiation buffer */
654 static BYTE do_term[] = { IAC, DO, TERMINAL_TYPE };
655 static BYTE will_term[] = { IAC, WILL, TERMINAL_TYPE };
656 static BYTE req_type[] = { IAC, SB, TERMINAL_TYPE, SEND, IAC, SE };
657 static BYTE type_is[] = { IAC, SB, TERMINAL_TYPE, IS };
658 static BYTE do_eor[] = { IAC, DO, EOR, IAC, WILL, EOR };
659 static BYTE will_eor[] = { IAC, WILL, EOR, IAC, DO, EOR };
660 static BYTE do_bin[] = { IAC, DO, BINARY, IAC, WILL, BINARY };
661 static BYTE will_bin[] = { IAC, WILL, BINARY, IAC, DO, BINARY };
662 #if 0
663 static BYTE do_tmark[] = { IAC, DO, TIMING_MARK };
664 static BYTE will_tmark[] = { IAC, WILL, TIMING_MARK };
665 static BYTE wont_sga[] = { IAC, WONT, SUPPRESS_GA };
666 static BYTE dont_sga[] = { IAC, DONT, SUPPRESS_GA };
667 #endif
668 static BYTE wont_echo[] = { IAC, WONT, ECHO_OPTION };
669 static BYTE dont_echo[] = { IAC, DONT, ECHO_OPTION };
670 static BYTE will_naws[] = { IAC, WILL, NAWS };
671 
672     /* Perform terminal-type negotiation */
673     rc = send_packet (csock, do_term, sizeof(do_term),
674                         "IAC DO TERMINAL_TYPE");
675     if (rc < 0) return -1;
676 
677     rc = expect (csock, will_term, sizeof(will_term),
678                         "IAC WILL TERMINAL_TYPE");
679     if (rc < 0) return -1;
680 
681     /* Request terminal type */
682     rc = send_packet (csock, req_type, sizeof(req_type),
683                         "IAC SB TERMINAL_TYPE SEND IAC SE");
684     if (rc < 0) return -1;
685 
686     rc = recv_packet (csock, buf, sizeof(buf)-2, SE);
687     if (rc < 0) return -1;
688 
689     /* Ignore Negotiate About Window Size */
690     if (rc >= (int)sizeof(will_naws) &&
691         memcmp (buf, will_naws, sizeof(will_naws)) == 0)
692     {
693         memmove(buf, &buf[sizeof(will_naws)], (rc - sizeof(will_naws)));
694         rc -= sizeof(will_naws);
695     }
696 
697     if (rc < (int)(sizeof(type_is) + 2)
698         || memcmp(buf, type_is, sizeof(type_is)) != 0
699         || buf[rc-2] != IAC || buf[rc-1] != SE) {
700         TNSDEBUG2("console: DBG008: Expected IAC SB TERMINAL_TYPE IS\n");
701         return -1;
702     }
703     buf[rc-2] = '\0';
704     termtype = (char *)(buf + sizeof(type_is));
705     TNSDEBUG2("console: DBG009: Received IAC SB TERMINAL_TYPE IS %s IAC SE\n",
706             termtype);
707 
708     /* Check terminal type string for device name suffix */
709     s = strchr (termtype, '@');
710     if(s!=NULL)
711     {
712         if(strlen(s)<16)
713         {
714             strlcpy(group,&s[1],16);
715         }
716     }
717     else
718     {
719         group[0]=0;
720     }
721 
722     if (s != NULL && sscanf (s, "@%hx%c", &devnum,&c) == 1)
723     {
724         *devn = devnum;
725         group[0]=0;
726     }
727     else
728     {
729         *devn = 0xFFFF;
730     }
731 
732     /* Test for non-display terminal type */
733     if (memcmp(termtype, "IBM-", 4) != 0)
734     {
735 #if 0
736         /* Perform line mode negotiation */
737         rc = send_packet (csock, do_tmark, sizeof(do_tmark),
738                             "IAC DO TIMING_MARK");
739         if (rc < 0) return -1;
740 
741         rc = expect (csock, will_tmark, sizeof(will_tmark),
742                             "IAC WILL TIMING_MARK");
743         if (rc < 0) return 0;
744 
745         rc = send_packet (csock, wont_sga, sizeof(wont_sga),
746                             "IAC WONT SUPPRESS_GA");
747         if (rc < 0) return -1;
748 
749         rc = expect (csock, dont_sga, sizeof(dont_sga),
750                             "IAC DONT SUPPRESS_GA");
751         if (rc < 0) return -1;
752 #endif
753 
754         if (memcmp(termtype, "ANSI", 4) == 0)
755         {
756             rc = send_packet (csock, wont_echo, sizeof(wont_echo),
757                                 "IAC WONT ECHO");
758             if (rc < 0) return -1;
759 
760             rc = expect (csock, dont_echo, sizeof(dont_echo),
761                                 "IAC DONT ECHO");
762             if (rc < 0) return -1;
763         }
764 
765         /* Return printer-keyboard terminal class */
766         *class = 'K';
767         *model = '-';
768         *extatr = '-';
769         return 0;
770     }
771 
772     /* Determine display terminal model */
773     if (memcmp(termtype+4,"DYNAMIC",7) == 0) {
774         *model = 'X';
775         *extatr = 'Y';
776     } else {
777         if (!(memcmp(termtype+4, "3277", 4) == 0
778               || memcmp(termtype+4, "3270", 4) == 0
779               || memcmp(termtype+4, "3178", 4) == 0
780               || memcmp(termtype+4, "3278", 4) == 0
781               || memcmp(termtype+4, "3179", 4) == 0
782               || memcmp(termtype+4, "3180", 4) == 0
783               || memcmp(termtype+4, "3287", 4) == 0
784               || memcmp(termtype+4, "3279", 4) == 0))
785             return -1;
786 
787         *model = '2';
788         *extatr = 'N';
789 
790         if (termtype[8]=='-') {
791             if (termtype[9] < '1' || termtype[9] > '5')
792                 return -1;
793             *model = termtype[9];
794             if (memcmp(termtype+4, "328",3) == 0) *model = '2';
795             if (memcmp(termtype+10, "-E", 2) == 0)
796                 *extatr = 'Y';
797         }
798     }
799 
800     /* Perform end-of-record negotiation */
801     rc = send_packet (csock, do_eor, sizeof(do_eor),
802                         "IAC DO EOR IAC WILL EOR");
803     if (rc < 0) return -1;
804 
805     rc = expect (csock, will_eor, sizeof(will_eor),
806                         "IAC WILL EOR IAC DO EOR");
807     if (rc < 0) return -1;
808 
809     /* Perform binary negotiation */
810     rc = send_packet (csock, do_bin, sizeof(do_bin),
811                         "IAC DO BINARY IAC WILL BINARY");
812     if (rc < 0) return -1;
813 
814     rc = expect (csock, will_bin, sizeof(will_bin),
815                         "IAC WILL BINARY IAC DO BINARY");
816     if (rc < 0) return -1;
817 
818     /* Return display terminal class */
819     if (memcmp(termtype+4,"3287",4)==0) *class='P';
820     else *class = 'D';
821     return 0;
822 
823 } /* end function negotiate */
824 
825 
826 /*-------------------------------------------------------------------*/
827 /* SUBROUTINE TO RECEIVE 3270 DATA FROM THE CLIENT                   */
828 /* This subroutine receives bytes from the client and appends them   */
829 /* to any data already in the 3270 receive buffer.                   */
830 /* If zero bytes are received, this means the client has closed the  */
831 /* connection, and attention and unit check status is returned.      */
832 /* If the buffer is filled before receiving end of record, then      */
833 /* attention and unit check status is returned.                      */
834 /* If the data ends with IAC followed by EOR_MARK, then the data     */
835 /* is scanned to remove any IAC sequences, attention status is       */
836 /* returned, and the read pending indicator is set.                  */
837 /* If the data accumulated in the buffer does not yet constitute a   */
838 /* complete record, then zero status is returned, and a further      */
839 /* call must be made to this subroutine when more data is available. */
840 /*-------------------------------------------------------------------*/
841 static BYTE
recv_3270_data(DEVBLK * dev)842 recv_3270_data (DEVBLK *dev)
843 {
844 int     rc;                             /* Return code               */
845 int     eor = 0;                        /* 1=End of record received  */
846 
847     /* If there is a complete data record already in the buffer
848        then discard it before reading more data */
849     if (dev->readpending)
850     {
851         dev->rlen3270 = 0;
852         dev->readpending = 0;
853     }
854 
855     /*
856         The following chunk of code was added to try and catch
857         a race condition that may or may no longer still exist.
858     */
859     TNSDEBUG1("console: DBG031: verifying data is available...\n");
860     {
861         fd_set readset;
862         struct timeval tv = {0,0};      /* (non-blocking poll) */
863 
864         FD_ZERO( &readset );
865         FD_SET( dev->fd, &readset );
866 
867         while ( (rc = select ( dev->fd+1, &readset, NULL, NULL, &tv )) < 0
868             && HSO_EINTR == HSO_errno )
869             ;   /* NOP (keep retrying if EINTR) */
870 
871         if (rc < 0)
872         {
873             TNSERROR("console: DBG032: select failed: %s\n", strerror(HSO_errno));
874             return 0;
875         }
876 
877         ASSERT(rc <= 1);
878 
879         if (!FD_ISSET(dev->fd, &readset))
880         {
881             ASSERT(rc == 0);
882             TNSDEBUG1("console: DBG033: no data available; returning 0...\n");
883             return 0;
884         }
885 
886         ASSERT(rc == 1);
887     }
888     TNSDEBUG1("console: DBG034: data IS available; attempting recv...\n");
889 
890     /* Receive bytes from client */
891     rc = recv (dev->fd, dev->buf + dev->rlen3270,
892                BUFLEN_3270 - dev->rlen3270, 0);
893 
894     if (rc < 0) {
895         if ( HSO_ECONNRESET == HSO_errno )
896             logmsg( _( "HHCTE014I %4.4X device %4.4X client %s connection reset\n" ),
897                 dev->devtype, dev->devnum, inet_ntoa(dev->ipaddr) );
898         else
899             TNSERROR("console: DBG023: recv: %s\n", strerror(HSO_errno));
900         dev->sense[0] = SENSE_EC;
901         return (CSW_ATTN | CSW_UC);
902     }
903 
904     /* If zero bytes were received then client has closed connection */
905     if (rc == 0) {
906         logmsg (_("HHCTE007I %4.4X device %4.4X client %s connection closed\n"),
907                 dev->devtype, dev->devnum, inet_ntoa(dev->ipaddr));
908         dev->sense[0] = SENSE_IR;
909         return (CSW_ATTN | CSW_UC | CSW_DE);
910     }
911 
912     /* Update number of bytes in receive buffer */
913     dev->rlen3270 += rc;
914 
915     /* Check whether Attn indicator was received */
916     if (dev->rlen3270 >= 2
917         && dev->buf[dev->rlen3270 - 2] == IAC
918         && dev->buf[dev->rlen3270 - 1] == BRK)
919         eor = 1;
920 
921     /* Check whether SysRq indicator was received */
922     if (dev->rlen3270 >= 2
923         && dev->buf[dev->rlen3270 - 2] == IAC
924         && dev->buf[dev->rlen3270 - 1] == IP)
925         eor = 1;
926 
927     /* Check whether end of record marker was received */
928     if (dev->rlen3270 >= 2
929         && dev->buf[dev->rlen3270 - 2] == IAC
930         && dev->buf[dev->rlen3270 - 1] == EOR_MARK)
931         eor = 1;
932 
933     /* If record is incomplete, test for buffer full */
934     if (eor == 0 && dev->rlen3270 >= BUFLEN_3270)
935     {
936         TNSDEBUG1("console: DBG010: 3270 buffer overflow\n");
937         dev->sense[0] = SENSE_DC;
938         return (CSW_ATTN | CSW_UC);
939     }
940 
941     /* Return zero status if record is incomplete */
942     if (eor == 0)
943         return 0;
944 
945     /* Trace the complete 3270 data packet */
946     TNSDEBUG2("console: DBG011: Packet received length=%d\n",
947             dev->rlen3270);
948     packet_trace (dev->buf, dev->rlen3270);
949 
950     /* Strip off the telnet EOR marker */
951     dev->rlen3270 -= 2;
952 
953     /* Remove any embedded IAC commands */
954     dev->rlen3270 = remove_iac (dev->buf, dev->rlen3270);
955 
956     /* Set the read pending indicator and return attention status */
957     dev->readpending = 1;
958     return (CSW_ATTN);
959 
960 } /* end function recv_3270_data */
961 
962 
963 /*-------------------------------------------------------------------*/
964 /* SUBROUTINE TO SOLICIT 3270 DATA FROM THE CLIENT                   */
965 /* This subroutine sends a Read or Read Modified command to the      */
966 /* client and then receives the data into the 3270 receive buffer.   */
967 /* This subroutine is called by loc3270_execute_ccw as a result of   */
968 /* processing a Read Buffer CCW, or a Read Modified CCW when no      */
969 /* data is waiting in the 3270 read buffer.  It waits until the      */
970 /* client sends end of record.  Certain tn3270 clients fail to       */
971 /* flush their buffer until the user presses an attention key;       */
972 /* these clients cause this routine to hang and are not supported.   */
973 /* Since this routine is only called while a channel program is      */
974 /* active on the device, we can rely on the dev->busy flag to        */
975 /* prevent the connection thread from issuing a read and capturing   */
976 /* the incoming data intended for this routine.                      */
977 /* The caller MUST hold the device lock.                             */
978 /* Returns zero status if successful, or unit check if error.        */
979 /*-------------------------------------------------------------------*/
980 static BYTE
solicit_3270_data(DEVBLK * dev,BYTE cmd)981 solicit_3270_data (DEVBLK *dev, BYTE cmd)
982 {
983 int             rc;                     /* Return code               */
984 int             len;                    /* Data length               */
985 BYTE            buf[32];                /* tn3270 write buffer       */
986 
987     /* Clear the inbound buffer of any unsolicited
988        data accumulated by the connection thread */
989     dev->rlen3270 = 0;
990     dev->readpending = 0;
991 
992     /* Construct a 3270 read command in the outbound buffer */
993     len = 0;
994     buf[len++] = cmd;
995 
996     /* Append telnet EOR marker to outbound buffer */
997     buf[len++] = IAC;
998     buf[len++] = EOR_MARK;
999 
1000     /* Send the 3270 read command to the client */
1001     rc = send_packet(dev->fd, buf, len, "3270 Read Command");
1002     if (rc < 0)
1003     {
1004         dev->sense[0] = SENSE_DC;
1005         return (CSW_UC);
1006     }
1007 
1008     /* Receive response data from the client */
1009     do {
1010         len = dev->rlen3270;
1011         rc = recv_3270_data (dev);
1012         TNSDEBUG2("console: DBG012: read buffer: %d bytes received\n",
1013                 dev->rlen3270 - len);
1014     } while(rc == 0);
1015 
1016     /* Close the connection if an error occurred */
1017     if (rc & CSW_UC)
1018     {
1019         dev->connected = 0;
1020         dev->fd = -1;
1021         dev->sense[0] = SENSE_DC;
1022 
1023         return (CSW_UC);
1024     }
1025 
1026     /* Return zero status to indicate response received */
1027     return 0;
1028 
1029 } /* end function solicit_3270_data */
1030 
1031 
1032 /*-------------------------------------------------------------------*/
1033 /* SUBROUTINE TO RECEIVE 1052/3215 DATA FROM THE CLIENT              */
1034 /* This subroutine receives keyboard input characters from the       */
1035 /* client, and appends the characters to any data already in the     */
1036 /* keyboard buffer.                                                  */
1037 /* If zero bytes are received, this means the client has closed the  */
1038 /* connection, and attention and unit check status is returned.      */
1039 /* If the buffer is filled before receiving end of record, then      */
1040 /* attention and unit check status is returned.                      */
1041 /* If a break indication (control-C, IAC BRK, or IAC IP) is          */
1042 /* received, the attention and unit exception status is returned.    */
1043 /* When carriage return and line feed (CRLF) is received, then       */
1044 /* the CRLF is discarded, the data in the keyboard buffer is         */
1045 /* translated to EBCDIC, the read pending indicator is set, and      */
1046 /* attention status is returned.                                     */
1047 /* If CRLF has not yet been received, then zero status is returned,  */
1048 /* and a further call must be made to this subroutine when more      */
1049 /* data is available.                                                */
1050 /*-------------------------------------------------------------------*/
1051 static BYTE
recv_1052_data(DEVBLK * dev)1052 recv_1052_data (DEVBLK *dev)
1053 {
1054 int     num;                            /* Number of bytes received  */
1055 int     i;                              /* Array subscript           */
1056 BYTE    buf[BUFLEN_1052];               /* Receive buffer            */
1057 BYTE    c;                              /* Character work area       */
1058 
1059     /* Receive bytes from client */
1060     num = recv (dev->fd, buf, BUFLEN_1052, 0);
1061 
1062     /* Return unit check if error on receive */
1063     if (num < 0) {
1064         TNSERROR("console: DBG024: recv: %s\n", strerror(HSO_errno));
1065         dev->sense[0] = SENSE_EC;
1066         return (CSW_ATTN | CSW_UC);
1067     }
1068 
1069     /* If zero bytes were received then client has closed connection */
1070     if (num == 0) {
1071         logmsg (_("HHCTE008I Device %4.4X connection closed by client %s\n"),
1072                 dev->devnum, inet_ntoa(dev->ipaddr));
1073         dev->sense[0] = SENSE_IR;
1074         return (CSW_ATTN | CSW_UC);
1075     }
1076 
1077     /* Trace the bytes received */
1078     TNSDEBUG2("console: DBG013: Bytes received length=%d\n", num);
1079     packet_trace (buf, num);
1080 
1081     /* Copy received bytes to keyboard buffer */
1082     for (i = 0; i < num; i++)
1083     {
1084         /* Decrement keyboard buffer pointer if backspace received */
1085         if (buf[i] == 0x08)
1086         {
1087             if (dev->keybdrem > 0) dev->keybdrem--;
1088             continue;
1089         }
1090 
1091         /* Return unit exception if control-C received */
1092         if (buf[i] == 0x03)
1093         {
1094             dev->keybdrem = 0;
1095             return (CSW_ATTN | CSW_UX);
1096         }
1097 
1098         /* Return unit check if buffer is full */
1099         if (dev->keybdrem >= BUFLEN_1052)
1100         {
1101             TNSDEBUG1("console: DBG014: Console keyboard buffer overflow\n");
1102             dev->keybdrem = 0;
1103             dev->sense[0] = SENSE_EC;
1104             return (CSW_ATTN | CSW_UC);
1105         }
1106 
1107         /* Copy character to keyboard buffer */
1108         dev->buf[dev->keybdrem++] = buf[i];
1109 
1110         /* Decrement keyboard buffer pointer if telnet
1111            erase character sequence received */
1112         if (dev->keybdrem >= 2
1113             && dev->buf[dev->keybdrem - 2] == IAC
1114             && dev->buf[dev->keybdrem - 1] == EC)
1115         {
1116             dev->keybdrem -= 2;
1117             if (dev->keybdrem > 0) dev->keybdrem--;
1118             continue;
1119         }
1120 
1121         /* Zeroize keyboard buffer pointer if telnet
1122            erase line sequence received */
1123         if (dev->keybdrem >= 2
1124             && dev->buf[dev->keybdrem - 2] == IAC
1125             && dev->buf[dev->keybdrem - 1] == EL)
1126         {
1127             dev->keybdrem = 0;
1128             continue;
1129         }
1130 
1131         /* Zeroize keyboard buffer pointer if telnet
1132            carriage return sequence received */
1133         if (dev->keybdrem >= 2
1134             && dev->buf[dev->keybdrem - 2] == '\r'
1135             && dev->buf[dev->keybdrem - 1] == '\0')
1136         {
1137             dev->keybdrem = 0;
1138             continue;
1139         }
1140 
1141         /* Return unit exception if telnet break sequence received */
1142         if (dev->keybdrem >= 2
1143             && dev->buf[dev->keybdrem - 2] == IAC
1144             && (dev->buf[dev->keybdrem - 1] == BRK
1145                 || dev->buf[dev->keybdrem - 1] == IP))
1146         {
1147             dev->keybdrem = 0;
1148             return (CSW_ATTN | CSW_UX);
1149         }
1150 
1151         /* Return unit check with overrun if telnet CRLF
1152            sequence received and more data follows the CRLF */
1153         if (dev->keybdrem >= 2
1154             && dev->buf[dev->keybdrem - 2] == '\r'
1155             && dev->buf[dev->keybdrem - 1] == '\n'
1156             && i < num - 1)
1157         {
1158             TNSDEBUG1("console: DBG015: Console keyboard buffer overrun\n");
1159             dev->keybdrem = 0;
1160             dev->sense[0] = SENSE_OR;
1161             return (CSW_ATTN | CSW_UC);
1162         }
1163 
1164     } /* end for(i) */
1165 
1166     /* Return zero status if CRLF was not yet received */
1167     if (dev->keybdrem < 2
1168         || dev->buf[dev->keybdrem - 2] != '\r'
1169         || dev->buf[dev->keybdrem - 1] != '\n')
1170         return 0;
1171 
1172     /* Trace the complete keyboard data packet */
1173     TNSDEBUG2("console: DBG016: Packet received length=%d\n",
1174             dev->keybdrem);
1175     packet_trace (dev->buf, dev->keybdrem);
1176 
1177     /* Strip off the CRLF sequence */
1178     dev->keybdrem -= 2;
1179 
1180     /* Translate the keyboard buffer to EBCDIC */
1181     for (i = 0; i < dev->keybdrem; i++)
1182     {
1183         c = dev->buf[i];
1184         dev->buf[i] = (isprint(c) ? host_to_guest(c) : SPACE);
1185     } /* end for(i) */
1186 
1187     /* Trace the EBCDIC input data */
1188     TNSDEBUG2("console: DBG017: Input data line length=%d\n",
1189             dev->keybdrem);
1190     packet_trace (dev->buf, dev->keybdrem);
1191 
1192     /* Return attention status */
1193     return (CSW_ATTN);
1194 
1195 } /* end function recv_1052_data */
1196 
1197 /* The following code and functions are here
1198  * to build a more fancy logo
1199  */
1200 #define SF_ATTR_PROTECTED   0x20
1201 #define SF_ATTR_NUMERIC     0x10
1202 /* One of */
1203 #define SF_ATTR_WDISPNSEL   0x00
1204 #define SF_ATTR_WDISPSEL    0x04
1205 #define SF_ATTR_HIGHLIGHT   0x08
1206 #define SF_ATTR_INVISIBLE   0x0C
1207 
1208 #define SF_ATTR_MDT         0x01
1209 
1210 /*
1211 static char *herclogo[]={
1212     " HHH          HHH   The S/370, ESA/390 and z/Architecture",
1213     " HHH          HHH                 Emulator",
1214     " HHH          HHH",
1215     " HHH          HHH  EEEE RRR   CCC U  U L    EEEE  SSS",
1216     " HHHHHHHHHHHHHHHH  E    R  R C    U  U L    E    S",
1217     " HHHHHHHHHHHHHHHH  EEE  RRR  C    U  U L    EEE   SS",
1218     " HHHHHHHHHHHHHHHH  E    R R  C    U  U L    E       S",
1219     " HHH          HHH  EEEE R  R  CCC  UU  LLLL EEEE SSS ",
1220     " HHH          HHH",
1221     " HHH          HHH",
1222     " HHH          HHH     My PC thinks it's a MAINFRAME",
1223     "",
1224     " Copyright (C) 1999-2010 Roger Bowler, Jan Jaeger, and others"};
1225     */
1226 
1227 static char *herclogo[]={
1228 "@ALIGN NONE",
1229 "@SBA 0,0",
1230 "@SF P",
1231 "Hercules Version  :",
1232 "@SF HP",
1233 "$(VERSION)",
1234 "@NL",
1235 "@SF P",
1236 "Host name         :",
1237 "@SF HP",
1238 "$(HOSTNAME)",
1239 "@NL",
1240 "@SF P",
1241 "Host OS           :",
1242 "@SF HP",
1243 "$(HOSTOS)-$(HOSTOSREL) $(HOSTOSVER)",
1244 "@NL",
1245 "@SF P",
1246 "Host Architecture :",
1247 "@SF HP",
1248 "$(HOSTARCH)",
1249 "@NL",
1250 "@SF P",
1251 "Processors        :",
1252 "@SF HP",
1253 "$(HOSTNUMCPUS)",
1254 "@NL",
1255 "@SF P",
1256 "Chanl Subsys      :",
1257 "@SF HP",
1258 "$(CSS)",
1259 "@NL",
1260 "@SF P",
1261 "Device number     :",
1262 "@SF HP",
1263 "$(CCUU)",
1264 "@NL",
1265 "@SF P",
1266 "Subchannel        :",
1267 "@SF HP",
1268 "$(SUBCHAN)",
1269 "@SF P",
1270 "@ALIGN LEFT",
1271 "",
1272 "",
1273 "           HHH          HHH   The S/370, ESA/390 and z/Architecture",
1274 "           HHH          HHH                 Emulator",
1275 "           HHH          HHH",
1276 "           HHH          HHH  EEEE RRR   CCC U  U L    EEEE  SSS",
1277 "           HHHHHHHHHHHHHHHH  E    R  R C    U  U L    E    S",
1278 "           HHHHHHHHHHHHHHHH  EEE  RRR  C    U  U L    EEE   SS",
1279 "           HHHHHHHHHHHHHHHH  E    R R  C    U  U L    E       S",
1280 "           HHH          HHH  EEEE R  R  CCC  UU  LLLL EEEE SSS",
1281 "           HHH          HHH",
1282 "           HHH          HHH",
1283 "           HHH          HHH     My PC thinks it's a MAINFRAME",
1284 "",
1285 "           Copyright (C) 1999-2010 Roger Bowler, Jan Jaeger, and others"};
1286 
1287 #define LOGO_BUFFERSIZE 256;
1288 
buffer_addchar(char * b,size_t * l,size_t * al,char c)1289 static char *buffer_addchar(char *b,size_t *l,size_t *al,char c)
1290 {
1291     size_t len;
1292     size_t alen;
1293     len=*l;
1294     alen=*al;
1295     if(len>=alen)
1296     {
1297         if(!alen)
1298         {
1299             alen=LOGO_BUFFERSIZE;
1300             b=malloc(alen);
1301             if(!b)
1302             {
1303                 return NULL;
1304             }
1305         }
1306         else
1307         {
1308             alen+=LOGO_BUFFERSIZE;
1309             b=realloc(b,alen);
1310             if(!b)
1311             {
1312                 return NULL;
1313             }
1314         }
1315     }
1316     b[len++]=c;
1317     *al=alen;
1318     *l=len;
1319     return b;
1320 }
1321 
buffer_addstring(char * b,size_t * l,size_t * al,char * s)1322 static char *buffer_addstring(char *b,size_t *l,size_t *al,char *s)
1323 {
1324     size_t i;
1325     for(i=0;s[i]!=0;i++)
1326     {
1327         b=buffer_addchar(b,l,al,s[i]);
1328         if(!b)
1329         {
1330             return NULL;
1331         }
1332     }
1333     return b;
1334 }
1335 
buffer_addsba(char * b,size_t * l,size_t * al,int x,int y)1336 static char *buffer_addsba(char *b,size_t *l,size_t *al,int x, int y)
1337 {
1338     int pos;
1339     pos=x*80+y;
1340     b=buffer_addchar(b,l,al,0x11);
1341     if(!b) return NULL;
1342     b=buffer_addchar(b,l,al,sba_code[pos>>6]);
1343     if(!b) return NULL;
1344     b=buffer_addchar(b,l,al,sba_code[pos & 0x3f]);
1345     return b;
1346 }
buffer_addsf(char * b,size_t * l,size_t * al,int a)1347 static char *buffer_addsf(char *b,size_t *l,size_t *al,int a)
1348 {
1349     b=buffer_addchar(b,l,al,0x1d);
1350     if(!b) return NULL;
1351     b=buffer_addchar(b,l,al,sba_code[a & 0x3f]);
1352     return b;
1353 }
1354 
1355 #define ALIGN_NONE 0
1356 #define ALIGN_CENTER 1
1357 #define ALIGN_LEFT 2
1358 #define ALIGN_RIGHT 3
build_logo(char ** logodata,size_t logosize,size_t * blen)1359 static char *build_logo(char **logodata,size_t logosize,size_t *blen)
1360 {
1361     size_t  len;
1362     size_t  alen;
1363     char *bfr;
1364     char    *cline;
1365     size_t i,j;
1366     char    *verb;
1367     char    *rest;
1368     int     xpos,ypos;
1369     int     attr;
1370     int     align;
1371     char    *wrk;
1372 
1373     bfr=NULL;
1374     len=0;
1375     alen=0;
1376     bfr=buffer_addchar(bfr,&len,&alen,0xf5);
1377     bfr=buffer_addchar(bfr,&len,&alen,0x42);
1378     if(bfr==NULL)
1379     {
1380         *blen=0;
1381         return NULL;
1382     }
1383     align=ALIGN_NONE;
1384     xpos=0;
1385     ypos=0;
1386     attr=SF_ATTR_PROTECTED;
1387     for(i=0;i<logosize;i++)
1388     {
1389         cline=malloc(strlen(logodata[i])+1);
1390         strcpy(cline,logodata[i]);
1391         while(1)
1392         {
1393             if(cline[0]!='@')
1394             {
1395 #if defined(OPTION_CONFIG_SYMBOLS)
1396                 wrk=resolve_symbol_string(cline);
1397                 free(cline);
1398                 cline=wrk;
1399 #endif
1400                 switch(align)
1401                 {
1402                     case ALIGN_RIGHT:
1403                         ypos=strlen(cline);
1404                         if(ypos<80)
1405                         {
1406                             ypos=80-ypos;
1407                         }
1408                         else
1409                         {
1410                             ypos=0;
1411                         }
1412                         break;
1413                     case ALIGN_CENTER:
1414                         ypos=strlen(cline);
1415                         if(ypos<80)
1416                         {
1417                             ypos=(80-ypos)/2;
1418                         }
1419                         break;
1420                     case ALIGN_LEFT:
1421                         ypos=0;
1422                         break;
1423                     default:
1424                         break;
1425                 }
1426                 bfr=buffer_addsba(bfr,&len,&alen,xpos,ypos);
1427                 bfr=buffer_addsf(bfr,&len,&alen,attr);
1428                 if(align==ALIGN_NONE)
1429                 {
1430                     ypos+=strlen(cline);
1431                     ypos++;
1432                 }
1433                 else
1434                 {
1435                     xpos++;
1436                     ypos=0;
1437                 }
1438                 bfr=buffer_addstring(bfr,&len,&alen,(char *)translate_to_ebcdic(cline));
1439                 break;
1440             }
1441             verb=strtok(cline," \t");
1442             if(verb==NULL)
1443             {
1444                 break;
1445             }
1446             rest=strtok(NULL," \t");
1447             if(strcasecmp(verb,"@sba")==0)
1448             {
1449                 if(rest==NULL)
1450                 {
1451                     break;
1452                 }
1453                 wrk=strtok(rest,",");
1454                 if(wrk!=NULL)
1455                 {
1456                     xpos=atoi(wrk);
1457                 }
1458                 wrk=strtok(NULL,",");
1459                 if(wrk!=NULL)
1460                 {
1461                     ypos=atoi(wrk);
1462                 }
1463                 break;
1464             }
1465             if(strcasecmp(verb,"@sf")==0)
1466             {
1467                 attr=SF_ATTR_PROTECTED;
1468                 if(rest==NULL)
1469                 {
1470                     break;
1471                 }
1472                 for(j=0;rest[j]!=0;j++)
1473                 {
1474                     switch(rest[j])
1475                     {
1476                         case 'h':
1477                         case 'H':
1478                             attr|=SF_ATTR_HIGHLIGHT;
1479                             break;
1480                         case 'i':
1481                         case 'I':
1482                             attr&=~SF_ATTR_PROTECTED;
1483                             break;
1484                         default:
1485                             break;
1486                     }
1487                 }
1488                 break;
1489             }
1490             if(strcasecmp(verb,"@nl")==0)
1491             {
1492                 xpos++;
1493                 ypos=0;
1494                 break;
1495             }
1496             if(strcasecmp(verb,"@align")==0)
1497             {
1498                 align=ALIGN_NONE;
1499                 if(rest==NULL)
1500                 {
1501                     break;
1502                 }
1503                 while(1)
1504                 {
1505                     if(strcasecmp(rest,"center")==0)
1506                     {
1507                         align=ALIGN_CENTER;
1508                         break;
1509                     }
1510                     if(strcasecmp(rest,"right")==0)
1511                     {
1512                         align=ALIGN_RIGHT;
1513                         break;
1514                     }
1515                     if(strcasecmp(rest,"none")==0)
1516                     {
1517                         align=ALIGN_NONE;
1518                         break;
1519                     }
1520                     if(strcasecmp(rest,"left")==0)
1521                     {
1522                         align=ALIGN_LEFT;
1523                         break;
1524                     }
1525                     break;
1526                 }
1527                 break;
1528             }
1529             break;
1530         }
1531         free(cline);
1532     }
1533     bfr=buffer_addchar(bfr,&len,&alen,IAC);
1534     bfr=buffer_addchar(bfr,&len,&alen,EOR_MARK);
1535     *blen=len;
1536     return bfr;
1537 }
1538 
1539 /*-------------------------------------------------------------------*/
1540 /* NEW CLIENT CONNECTION THREAD                                      */
1541 /*-------------------------------------------------------------------*/
1542 static void *
connect_client(int * csockp)1543 connect_client (int *csockp)
1544 {
1545 int                     rc;             /* Return code               */
1546 DEVBLK                 *dev;            /* -> Device block           */
1547 size_t                  len;            /* Data length               */
1548 int                     csock;          /* Socket for conversation   */
1549 struct sockaddr_in      client;         /* Client address structure  */
1550 socklen_t               namelen;        /* Length of client structure*/
1551 char                   *clientip;       /* Addr of client ip address */
1552 U16                     devnum;         /* Requested device number   */
1553 BYTE                    class;          /* D=3270, P=3287, K=3215/1052 */
1554 BYTE                    model;          /* 3270 model (2,3,4,5,X)    */
1555 BYTE                    extended;       /* Extended attributes (Y,N) */
1556 char                    buf[1920];       /* Message buffer            */
1557 char                    conmsg[256];    /* Connection message        */
1558 char                    devmsg[64];     /* Device message            */
1559 char                    hostmsg[256];   /* Host ID message           */
1560 char                    num_procs[16];  /* #of processors string     */
1561 char                    rejmsg[256];    /* Rejection message         */
1562 char                    group[16];      /* Console group             */
1563 size_t                  logoheight;
1564 char                    *logobfr;
1565 char                    *logoout;
1566 
1567     logobfr=NULL;
1568     /* Load the socket address from the thread parameter */
1569     csock = *csockp;
1570 
1571     /* Obtain the client's IP address */
1572     namelen = sizeof(client);
1573     rc = getpeername (csock, (struct sockaddr *)&client, &namelen);
1574 
1575     /* Log the client's IP address and hostname */
1576     clientip = strdup(inet_ntoa(client.sin_addr));
1577 
1578 #if 0
1579     // The following isn't really needed and hangs under unusual
1580     // network configuration settings and thus has been removed.
1581     {
1582         struct hostent*  pHE;           /* Addr of hostent structure */
1583         char*            clientname;    /* Addr of client hostname   */
1584 
1585         pHE = gethostbyaddr ((unsigned char*)(&client.sin_addr),
1586                             sizeof(client.sin_addr), AF_INET);
1587 
1588         if (pHE != NULL && pHE->h_name != NULL
1589         && pHE->h_name[0] != '\0') {
1590             clientname = (char*) pHE->h_name;
1591         } else {
1592             clientname = "host name unknown";
1593         }
1594 
1595         TNSDEBUG1("console: DBG018: Received connection from %s (%s)\n",
1596                 clientip, clientname);
1597     }
1598 #else
1599     TNSDEBUG1("console: DBG018: Received connection from %s\n",
1600             clientip );
1601 #endif
1602 
1603     /* Negotiate telnet parameters */
1604     rc = negotiate (csock, &class, &model, &extended, &devnum, group);
1605     if (rc != 0)
1606     {
1607         close_socket (csock);
1608         if (clientip) free(clientip);
1609         return NULL;
1610     }
1611 
1612     /* Look for an available console device */
1613     for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
1614     {
1615         /* Loop if the device is invalid */
1616         if ( !dev->allocated )
1617             continue;
1618 
1619         /* Loop if non-matching device type */
1620         if (class == 'D' && dev->devtype != 0x3270)
1621             continue;
1622 
1623         if (class == 'P' && dev->devtype != 0x3287)
1624             continue;
1625 
1626         if (class == 'K' && dev->devtype != 0x1052
1627             && dev->devtype != 0x3215)
1628             continue;
1629 
1630         /* Loop if a specific device number was requested and
1631            this device is not the requested device number */
1632         if (devnum != 0xFFFF && dev->devnum != devnum)
1633             continue;
1634 
1635         /* Loop if no specific device number was requested, and
1636            either a group was requested OR the device is in a group,
1637            and the device group does not match the requested group */
1638         if (devnum==0xFFFF && (group[0] || dev->filename[0]))
1639         {
1640             if (strncasecmp(group,dev->filename,16)!=0)
1641             {
1642                 continue;
1643             }
1644         }
1645 
1646         /* Obtain the device lock */
1647         obtain_lock (&dev->lock);
1648 
1649         /* Test for available device */
1650         if (dev->connected == 0)
1651         {
1652             /* Check ipaddr mask to see if client allowed on this device */
1653             if ( (client.sin_addr.s_addr & dev->acc_ipmask) != dev->acc_ipaddr )
1654             {
1655                 release_lock (&dev->lock);
1656                 if ( 0xFFFF == devnum )  /* If they did NOT request a spe- */
1657                     continue;            /* cifc devnum, then keep looking */
1658                 dev = NULL;              /* Otherwise they did,            */
1659                 break;                   /* but it's not available         */
1660             }
1661 
1662             /* Claim this device for the client */
1663             dev->connected = 1;
1664             dev->fd = csock;
1665             dev->ipaddr = client.sin_addr;
1666             dev->mod3270 = model;
1667             dev->eab3270 = (extended == 'Y' ? 1 : 0);
1668 
1669             /* Reset the console device */
1670             dev->readpending = 0;
1671             dev->rlen3270 = 0;
1672             dev->keybdrem = 0;
1673 
1674             memset (&dev->scsw, 0, sizeof(SCSW));
1675             memset (&dev->pciscsw, 0, sizeof(SCSW));
1676             dev->busy = dev->reserved = dev->suspended =
1677             dev->pending = dev->pcipending = dev->attnpending = 0;
1678 
1679             release_lock (&dev->lock);
1680 
1681             break;
1682         }
1683 
1684         /* Release the device lock */
1685         release_lock (&dev->lock);
1686 
1687     } /* end for(dev) */
1688 
1689     /* Build connection message for client */
1690 
1691     if ( cons_hostinfo.num_procs > 1 )
1692         snprintf( num_procs, sizeof(num_procs), "MP=%d", cons_hostinfo.num_procs );
1693     else
1694         strlcpy( num_procs, "UP", sizeof(num_procs) );
1695 
1696     snprintf
1697     (
1698         hostmsg, sizeof(hostmsg),
1699 
1700         "running on %s (%s-%s.%s %s %s)"
1701 
1702         ,cons_hostinfo.nodename
1703         ,cons_hostinfo.sysname
1704         ,cons_hostinfo.release
1705         ,cons_hostinfo.version
1706         ,cons_hostinfo.machine
1707         ,num_procs
1708     );
1709     snprintf (conmsg, sizeof(conmsg),
1710                 "Hercules version %s built on %s %s",
1711                 VERSION, __DATE__, __TIME__);
1712 
1713     /* Reject the connection if no available console device */
1714     if (dev == NULL)
1715     {
1716         /* Build the rejection message */
1717         if (devnum == 0xFFFF)
1718         {
1719             if(!group[0])
1720             {
1721                 snprintf (rejmsg, sizeof(rejmsg),
1722                         "Connection rejected, no available %s device",
1723                         (class=='D' ? "3270" : (class=='P' ? "3287" : "1052 or 3215")));
1724             }
1725             else
1726             {
1727                 snprintf (rejmsg, sizeof(rejmsg),
1728                         "Connection rejected, no available %s devices in the %s group",
1729                         (class=='D' ? "3270" : (class=='P' ? "3287" : "1052 or 3215")),group);
1730             }
1731         }
1732         else
1733         {
1734             snprintf (rejmsg, sizeof(rejmsg),
1735                     "Connection rejected, device %4.4X unavailable",
1736                     devnum);
1737         }
1738 
1739         TNSDEBUG1( "DBG019: %s\n", rejmsg);
1740 
1741         /* Send connection rejection message to client */
1742         if (class != 'K')
1743         {
1744             len = snprintf (buf, sizeof(buf),
1745                         "\xF5\x40\x11\x40\x40\x1D\x60%s"
1746                         "\x11\xC1\x50\x1D\x60%s"
1747                         "\x11\xC2\x60\x1D\x60%s",
1748                         translate_to_ebcdic(conmsg),
1749                         translate_to_ebcdic(hostmsg),
1750                         translate_to_ebcdic(rejmsg));
1751 
1752             if (len < sizeof(buf))
1753             {
1754                 buf[len++] = IAC;
1755             }
1756             else
1757             {
1758                 ASSERT(FALSE);
1759             }
1760 
1761             if (len < sizeof(buf))
1762             {
1763                 buf[len++] = EOR_MARK;
1764             }
1765             else
1766             {
1767                 ASSERT(FALSE);
1768             }
1769         }
1770         else
1771         {
1772             len = snprintf (buf, sizeof(buf), "%s\r\n%s\r\n%s\r\n", conmsg, hostmsg, rejmsg);
1773         }
1774 
1775         if (class != 'P')  /* do not write connection resp on 3287 */
1776         {
1777             rc = send_packet (csock, (BYTE *)buf, len, "CONNECTION RESPONSE");
1778         }
1779 
1780         /* Close the connection and terminate the thread */
1781         SLEEP (5);
1782         close_socket (csock);
1783         if (clientip) free(clientip);
1784         return NULL;
1785     }
1786     else
1787     {
1788         snprintf (devmsg, sizeof(devmsg), "Connected to device %d:%4.4X",
1789                   SSID_TO_LCSS(dev->ssid), dev->devnum);
1790     }
1791 
1792     logmsg (_("HHCTE009I Client %s connected to %4.4X device %d:%4.4X\n"),
1793             clientip, dev->devtype, SSID_TO_LCSS(dev->ssid), dev->devnum);
1794 
1795     /* Send connection message to client */
1796     if (class != 'K')
1797     {
1798 #if defined(OPTION_CONFIG_SYMBOLS)
1799         set_symbol("VERSION",VERSION);
1800         set_symbol("BDATE",__DATE__);
1801         set_symbol("BTIME",__TIME__);
1802         set_symbol("HOSTNAME",cons_hostinfo.nodename);
1803         set_symbol("HOSTOS",cons_hostinfo.sysname);
1804         set_symbol("HOSTOSREL",cons_hostinfo.release);
1805         set_symbol("HOSTOSVER",cons_hostinfo.version);
1806         set_symbol("HOSTARCH",cons_hostinfo.machine);
1807         set_symbol("HOSTNUMCPUS",num_procs);
1808         set_symbol("LPARNAME",str_lparname());
1809         snprintf(conmsg,sizeof(conmsg),"%3.3X",dev->devnum);
1810         set_symbol("CUU",conmsg);
1811         snprintf(conmsg,sizeof(conmsg),"%3.3x",dev->devnum);
1812         set_symbol("cuu",conmsg);
1813         snprintf(conmsg,sizeof(conmsg),"%4.4X",dev->devnum);
1814   #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
1815         if (dev == sysblk.sysgdev)
1816            strncpy(conmsg,"SYSG",sizeof(conmsg));
1817   #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
1818         set_symbol("CCUU",conmsg);
1819         snprintf(conmsg,sizeof(conmsg),"%4.4x",dev->devnum);
1820         set_symbol("ccuu",conmsg);
1821         snprintf(conmsg,sizeof(conmsg),"%d",SSID_TO_LCSS(dev->ssid));
1822         set_symbol("CSS",conmsg);
1823         snprintf(conmsg,sizeof(conmsg),"%4.4X",dev->subchan);
1824         set_symbol("SUBCHAN",conmsg);
1825 #endif // defined(OPTION_CONFIG_SYMBOLS)
1826         if(sysblk.herclogo!=NULL)
1827         {
1828             logobfr=build_logo(sysblk.herclogo,sysblk.logolines,&len);
1829         }
1830         else
1831         {
1832             logoheight=sizeof(herclogo)/sizeof(char *);
1833             logobfr=build_logo(herclogo,logoheight,&len);
1834         }
1835         logoout=logobfr;
1836     }
1837     else
1838     {
1839         len = snprintf (buf, sizeof(buf), "%s\r\n%s\r\n%s\r\n",
1840                         conmsg, hostmsg, devmsg);
1841         logoout=buf;
1842     }
1843 
1844     if (class != 'P')  /* do not write connection resp on 3287 */
1845     {
1846         rc = send_packet (csock, (BYTE *)logoout, len, "CONNECTION RESPONSE");
1847     }
1848     if(logobfr)
1849     {
1850         free(logobfr);
1851     }
1852 
1853     /* Raise attention interrupt for the device,
1854        IF...
1855          (1) this is NOT a 3287 printer device, -AND-
1856          (2) this is NOT the System-370 mode initial power-on state
1857          and it is not the SYSG console
1858     */
1859     if (class != 'P'
1860   #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
1861         && dev != sysblk.sysgdev
1862   #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
1863         && !INITIAL_POWERON_370())
1864         device_attention (dev, CSW_DE);
1865 
1866     /* Try to detect dropped connections */
1867     socket_keepalive( csock, sysblk.kaidle, sysblk.kaintv, sysblk.kacnt );
1868 
1869     /* Signal connection thread to redrive its select loop */
1870     SIGNAL_CONSOLE_THREAD();
1871 
1872     if (clientip) free(clientip);
1873     return NULL;
1874 
1875 } /* end function connect_client */
1876 
1877 
1878 /*-------------------------------------------------------------------*/
1879 /* CONSOLE CONNECTION AND ATTENTION HANDLER THREAD                   */
1880 /*-------------------------------------------------------------------*/
1881 
1882 static int     console_cnslcnt  = 0;    /* count of connected terms  */
1883 static LOCK    console_lock;            /* console_cnslcnt lock      */
1884 static int     did_init         = 0;    /* console_lock initialized  */
1885 
console_shutdown(void * unused)1886 static void console_shutdown(void * unused)
1887 {
1888     UNREFERENCED(unused);
1889 
1890     obtain_lock( &console_lock );
1891     {
1892         console_cnslcnt = 0;
1893         SIGNAL_CONSOLE_THREAD();
1894     }
1895     release_lock( &console_lock );
1896 }
1897 
1898 static void *
console_connection_handler(void * arg)1899 console_connection_handler (void *arg)
1900 {
1901 int                    rc = 0;          /* Return code               */
1902 int                    lsock;           /* Socket for listening      */
1903 int                    csock;           /* Socket for conversation   */
1904 struct sockaddr_in    *server;          /* Server address structure  */
1905 fd_set                 readset;         /* Read bit map for select   */
1906 int                    maxfd;           /* Highest fd for select     */
1907 int                    optval;          /* Argument for setsockopt   */
1908 TID                    tidneg;          /* Negotiation thread id     */
1909 DEVBLK                *dev;             /* -> Device block           */
1910 BYTE                   unitstat;        /* Status after receive data */
1911 
1912     UNREFERENCED(arg);
1913 
1914     hdl_adsc("console_shutdown",console_shutdown, NULL);
1915 
1916     /* Display thread started message on control panel */
1917     logmsg (_("HHCTE001I Console connection thread started: "
1918             "tid="TIDPAT", pid=%d\n"),
1919             thread_id(), getpid());
1920 
1921     /* Get information about this system */
1922     init_hostinfo( &cons_hostinfo );
1923 
1924     /* Obtain a socket */
1925     lsock = socket (AF_INET, SOCK_STREAM, 0);
1926 
1927     if (lsock < 0)
1928     {
1929         TNSERROR("console: DBG025: socket: %s\n", strerror(HSO_errno));
1930         return NULL;
1931     }
1932 
1933     /* Allow previous instance of socket to be reused */
1934     optval = 1;
1935     setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR,
1936                 (GETSET_SOCKOPT_T*)&optval, sizeof(optval));
1937 
1938     /* Prepare the sockaddr structure for the bind */
1939     if(!( server = get_inet_socket(config_cnslport) ))
1940     {
1941         logmsg(_("HHCTE010E CNSLPORT statement invalid: %s\n"),
1942             config_cnslport);
1943         return NULL;
1944     }
1945 
1946     /* Attempt to bind the socket to the port */
1947     do
1948     {
1949         rc = bind (lsock, (struct sockaddr *)server, sizeof(struct sockaddr_in));
1950 
1951         if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break;
1952 
1953         logmsg (_("HHCTE002W Waiting for port %u to become free\n"),
1954                 ntohs(server->sin_port));
1955         SLEEP(10);
1956     }
1957     while (console_cnslcnt);
1958 
1959     if (rc != 0)
1960     {
1961         TNSERROR("console: DBG026: bind: %s\n", strerror(HSO_errno));
1962         return NULL;
1963     }
1964 
1965     /* Put the socket into listening state */
1966     if ((rc = listen (lsock, 10)) < 0)
1967     {
1968         TNSERROR("console: DBG027: listen: %s\n", strerror(HSO_errno));
1969         return NULL;
1970     }
1971 
1972     logmsg (_("HHCTE003I Waiting for console connection on port %u\n"),
1973             ntohs(server->sin_port));
1974 
1975     /* Handle connection requests and attention interrupts */
1976     for (;;)
1977     {
1978         /* Check if time to exit */
1979         int time_to_exit;
1980         obtain_lock( &console_lock );
1981         time_to_exit = console_cnslcnt <= 0 ? 1 : 0;
1982         release_lock( &console_lock );
1983         if (time_to_exit) break;
1984 
1985         /* Initialize the select parameters */
1986 
1987         FD_ZERO ( &readset ); maxfd=INT_MIN;
1988         FD_SET  ( lsock, &readset ); maxfd = lsock;
1989         SUPPORT_WAKEUP_CONSOLE_SELECT_VIA_PIPE( maxfd, &readset );
1990 
1991         /* Include the socket for each valid connected console */
1992         for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
1993         {
1994             if ( !dev->allocated) continue;
1995 
1996             obtain_lock( &dev->lock );
1997             {
1998                 if ( dev->console )
1999                 {
2000                     if ( dev->connected )
2001                     {
2002                         /* VERIFY that the file descriptor is valid.
2003                            If it's NOT, then IGNORE this console device
2004                            since it's thus obvious that SOMETHING has
2005                            gone wrong SOMEWHERE at some point! (some
2006                            sort of race condition SOMEWHERE, obviously)
2007                         */
2008                         if (dev->fd < 0)
2009                         {
2010                             // Ah-HA! We may have FINALLY found (or at
2011                             // least have gotten a little bit closer to
2012                             // finding) the ROOT CAUSE of our problematic
2013                             // "DBG028 select: Bad FIle Number" problem!
2014                             logmsg
2015                             (
2016                                 "\n"
2017                                 "*********** DBG028 CONSOLE BUG ***********\n"
2018                                 "device %4.4X: 'connected', but dev->fd = -1\n"
2019                                 "\n"
2020 
2021                                 ,dev->devnum
2022                             );
2023                             dev->connected = 0;  // (since it's not connected!)
2024                         }
2025                         else
2026                         {
2027                             /* Add it to our read set only if it's
2028                             not busy nor interrupt pending */
2029                             if (1
2030                                 && (!dev->busy || (dev->scsw.flag3 & SCSW3_AC_SUSP))
2031                                 && !IOPENDING(dev)
2032                                 && !(dev->scsw.flag3 & SCSW3_SC_PEND)
2033                             )
2034                             {
2035                                 FD_SET (dev->fd, &readset);
2036                                 if (dev->fd > maxfd) maxfd = dev->fd;
2037                             }
2038                         }
2039                     }
2040                     else // ( !dev->connected )
2041                     {
2042                         if ( dev->fd >= 0 )
2043                         {
2044                             close_socket ( dev->fd );
2045                             dev->fd = -1;
2046                         }
2047 
2048                     } /* if (dev->connected) */
2049 
2050                 } /* if (dev->console) */
2051             }
2052             release_lock( &dev->lock );
2053 
2054         } /* end for(dev) */
2055 
2056         /* Wait for a file descriptor to become ready */
2057         rc = select ( maxfd+1, &readset, NULL, NULL, NULL );
2058 
2059         /* Clear the pipe signal if necessary */
2060         RECV_CONSOLE_THREAD_PIPE_SIGNAL();
2061 
2062         /* Log select errors */
2063         if (rc < 0 )
2064         {
2065             int select_errno = HSO_errno; // (preserve orig errno)
2066             static int issue_errmsg = 1;  // (prevents msgs flood)
2067 
2068             if (EBADF == select_errno)
2069             {
2070                 // Don't issue message more frequently
2071                 // than once every second or so, just in
2072                 // case the condition that's causing it
2073                 // keeps reoccurring over and over...
2074 
2075                 static struct timeval  prev = {0,0};
2076                        struct timeval  curr;
2077                        struct timeval  diff;
2078 
2079                 gettimeofday( &curr, NULL );
2080                 timeval_subtract( &prev, &curr, &diff );
2081 
2082                 // Has it been longer than one second
2083                 // since we last issued this message?
2084 
2085                 if (diff.tv_sec >= 1)
2086                 {
2087                     issue_errmsg = 1;
2088                     prev.tv_sec  = curr.tv_sec;
2089                     prev.tv_usec = curr.tv_usec;
2090                 }
2091                 else
2092                     issue_errmsg = 0;   // (prevents msgs flood)
2093             }
2094             else
2095                 issue_errmsg = 1;
2096             if ( issue_errmsg && EINTR != select_errno )
2097             {
2098                 TNSERROR("console: DBG028: select: %s\n", strerror(select_errno));
2099                 usleep(50000); // (wait a bit; maybe it'll fix itself??)
2100             }
2101             continue;
2102         }
2103 
2104         /* If a client connection request has arrived then accept it */
2105         if (FD_ISSET(lsock, &readset))
2106         {
2107             /* Accept a connection and create conversation socket */
2108             csock = accept (lsock, NULL, NULL);
2109 
2110             if (csock < 0)
2111             {
2112                 TNSERROR("console: DBG029: accept: %s\n", strerror(HSO_errno));
2113                 continue;
2114             }
2115 
2116             /* Create a thread to complete the client connection */
2117             if ( create_thread (&tidneg, DETACHED,
2118                         connect_client, &csock, "connect_client")
2119                )
2120             {
2121                 TNSERROR("console: DBG030: connect_client create_thread: %s\n",
2122                         strerror(errno));
2123                 close_socket (csock);
2124             }
2125 
2126         } /* end if(FD_ISSET(lsock, &readset)) */
2127 
2128         /* Check if any connected client has data ready to send */
2129         for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
2130         {
2131             /* Obtain the device lock */
2132             obtain_lock (&dev->lock);
2133 
2134             /* Test for valid connected console with data available */
2135             if (1
2136                 && dev->allocated
2137                 && dev->console
2138                 && dev->connected
2139                 && (!dev->busy || (dev->scsw.flag3 & SCSW3_AC_SUSP))
2140                 && !( IOPENDING(dev) || (dev->scsw.flag3 & SCSW3_SC_PEND) )
2141                 && FD_ISSET (dev->fd, &readset)
2142             )
2143             {
2144                 /* Receive console input data from the client */
2145                 if ((dev->devtype == 0x3270) || (dev->devtype == 0x3287))
2146                     unitstat = recv_3270_data (dev);
2147                 else
2148                     unitstat = recv_1052_data (dev);
2149 
2150                 /* Nothing more to do if incomplete record received */
2151                 if (unitstat == 0)
2152                 {
2153                     release_lock (&dev->lock);
2154                     continue;
2155                 }
2156 
2157                 /* Close the connection if an error occurred */
2158                 if (unitstat & CSW_UC)
2159                 {
2160                     close_socket (dev->fd);
2161                     dev->fd = -1;
2162                     dev->connected = 0;
2163                 }
2164 
2165                 /* Indicate that data is available at the device */
2166                 if(dev->rlen3270)
2167                     dev->readpending = 1;
2168 
2169                 /* Release the device lock */
2170                 release_lock (&dev->lock);
2171 
2172                 /* Raise attention interrupt for the device */
2173 
2174                 /* Do NOT raise attention interrupt for 3287  */
2175                 /* Otherwise zVM loops after ENABLE ccuu     */
2176                 /* Following 5 lines are repeated on Hercules console: */
2177                 /* console: sending 3270 data */
2178                 /*   +0000   F5C2FFEF     */
2179                 /*   console: Packet received length=7 */
2180                 /*   +0000   016CD902 00FFEF */
2181                 /*           I do not know what is this */
2182                 /*   console: CCUU attention requests raised */
2183 
2184                 /* Do not raise attention interrupt for the SYSG console */
2185 
2186                 /* Do NOT raise attention interrupt if this is */
2187                 /* the System-370 mode initial power-on state */
2188 
2189                 if (1
2190                     && dev->connected
2191                     && dev->devtype != 0x3287
2192               #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
2193                     && dev != sysblk.sysgdev
2194               #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
2195                     && !INITIAL_POWERON_370()
2196                 )
2197                 {
2198                     rc = device_attention (dev, unitstat);
2199 
2200                     /* Trace the attention request */
2201                     TNSDEBUG2("console: DBG020: "
2202                             "%4.4X attention request %s; rc=%d\n",
2203                             dev->devnum,
2204                             (rc == 0 ? "raised" : "rejected"), rc);
2205                 }
2206 
2207               #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
2208                 /* For the SYSG console, generate an external interrupt */
2209                 if (dev == sysblk.sysgdev && dev->connected)
2210                 {
2211                     sclp_sysg_attention();
2212                 }
2213               #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
2214 
2215                 continue; /* (note: dev->lock already released) */
2216 
2217             } /* end if(data available) */
2218 
2219             /* Release the device lock */
2220             release_lock (&dev->lock);
2221 
2222         } /* end for(dev) */
2223 
2224     } /* end for */
2225 
2226     /* Close all connected terminals */
2227     for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
2228     {
2229         /* Obtain the device lock */
2230         obtain_lock (&dev->lock);
2231 
2232         /* Test for connected console with data available */
2233         if (dev->console
2234             && dev->fd>=0)
2235         {
2236             close_socket(dev->fd);
2237             dev->connected=0;
2238             dev->fd=-1;
2239         }
2240         release_lock (&dev->lock);
2241     }
2242 
2243     /* Close the listening socket */
2244     close_socket (lsock);
2245     free(server);
2246 
2247     logmsg (_("HHCTE004I Console connection thread terminated\n"));
2248     sysblk.cnsltid = 0;
2249 
2250     return NULL;
2251 
2252 } /* end function console_connection_handler */
2253 
2254 
2255 static int
console_initialise()2256 console_initialise()
2257 {
2258     int rc = 0;
2259 
2260     if (!did_init)
2261     {
2262         did_init = 1;
2263         initialize_lock( &console_lock );
2264     }
2265 
2266     obtain_lock( &console_lock );
2267     {
2268         console_cnslcnt++;
2269 
2270         if (!sysblk.cnsltid)
2271         {
2272             if ( create_thread (&sysblk.cnsltid, DETACHED,
2273                                 console_connection_handler, NULL,
2274                                 "console_connection_handler")
2275                )
2276             {
2277                 logmsg (_("HHCTE005E Cannot create console thread: %s\n"),
2278                         strerror(errno));
2279                 rc = 1;
2280             }
2281         }
2282     }
2283     release_lock( &console_lock );
2284 
2285     return rc;
2286 }
2287 
2288 
2289 static void
console_remove(DEVBLK * dev)2290 console_remove(DEVBLK *dev)
2291 {
2292     obtain_lock( &console_lock );
2293     {
2294         dev->connected = 0;
2295         dev->console = 0;
2296         dev->fd = -1;
2297 
2298         if (console_cnslcnt <= 0)
2299             logmsg(_("** BUG! console_remove() error! **\n"));
2300         else
2301             console_cnslcnt--;
2302 
2303         SIGNAL_CONSOLE_THREAD();
2304     }
2305     release_lock( &console_lock );
2306 }
2307 
2308 
2309 /*-------------------------------------------------------------------*/
2310 /* INITIALIZE THE 3270 DEVICE HANDLER                                */
2311 /*-------------------------------------------------------------------*/
2312 static int
loc3270_init_handler(DEVBLK * dev,int argc,char * argv[])2313 loc3270_init_handler ( DEVBLK *dev, int argc, char *argv[] )
2314 {
2315     int ac = 0;
2316 
2317     /* Indicate that this is a console device */
2318     dev->console = 1;
2319 
2320     /* Reset device dependent flags */
2321     dev->connected = 0;
2322 
2323     /* Set number of sense bytes */
2324     dev->numsense = 1;
2325 
2326     /* Set the size of the device buffer */
2327     dev->bufsize = BUFLEN_3270;
2328 
2329     if(!sscanf(dev->typname,"%hx",&(dev->devtype)))
2330         dev->devtype = 0x3270;
2331 
2332   #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
2333     /* Extra initialisation for the SYSG console */
2334     if (strcasecmp(dev->typname,"SYSG") == 0)
2335     {
2336         dev->pmcw.flag5 &= ~PMCW5_V; // Not a regular device
2337         if (sysblk.sysgdev != NULL)
2338         {
2339             logmsg(_("HHCTE017E Device %4.4X: Duplicate SYSG console definition\n"),
2340                 dev->devnum);
2341             return -1;
2342         }
2343     }
2344   #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
2345 
2346     /* Initialize the device identifier bytes */
2347     dev->devid[0] = 0xFF;
2348     dev->devid[1] = 0x32; /* Control unit type is 3274-1D */
2349     dev->devid[2] = 0x74;
2350     dev->devid[3] = 0x1D;
2351     dev->devid[4] = 0x32; /* Device type is 3278-2 */
2352     if ((dev->devtype & 0xFF)==0x70)
2353     {
2354         dev->devid[5] = 0x78;
2355         dev->devid[6] = 0x02;
2356     }
2357     else
2358     {
2359         dev->devid[5] = dev->devtype & 0xFF; /* device type is 3287-1 */
2360         dev->devid[6] = 0x01;
2361     }
2362     dev->numdevid = 7;
2363 
2364     dev->filename[0] = 0;
2365     dev->acc_ipaddr = 0;
2366     dev->acc_ipmask = 0;
2367 
2368     if (argc > 0)   // group name?
2369     {
2370         if ('*' == argv[ac][0] && '\0' == argv[ac][1])
2371             ;   // NOP (not really a group name; an '*' is
2372                 // simply used as an argument place holder)
2373         else
2374             strlcpy(dev->filename,argv[ac],sizeof(dev->filename));
2375 
2376         argc--; ac++;
2377         if (argc > 0)   // ip address?
2378         {
2379             if ((dev->acc_ipaddr = inet_addr(argv[ac])) == (in_addr_t)(-1))
2380             {
2381                 logmsg(_("HHCTE011E Device %4.4X: Invalid IP address: %s\n"),
2382                     dev->devnum, argv[ac]);
2383                 return -1;
2384             }
2385             else
2386             {
2387                 argc--; ac++;
2388                 if (argc > 0)   // ip addr mask?
2389                 {
2390                     if ((dev->acc_ipmask = inet_addr(argv[ac])) == (in_addr_t)(-1))
2391                     {
2392                         logmsg(_("HHCTE012E Device %4.4X: Invalid mask value: %s\n"),
2393                             dev->devnum, argv[ac]);
2394                         return -1;
2395                     }
2396                     else
2397                     {
2398                         argc--; ac++;
2399                         if (argc > 0)   // too many args?
2400                         {
2401                             logmsg(_("HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n"),
2402                                 dev->devnum, argv[ac] );
2403                             return -1;
2404                         }
2405                     }
2406                 }
2407                 else
2408                     dev->acc_ipmask = (in_addr_t)(-1);
2409             }
2410         }
2411     }
2412 
2413   #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
2414     /* Extra initialisation for the SYSG console */
2415     if (strcasecmp(dev->typname,"SYSG") == 0)
2416     {
2417         /* Save the address of the SYSG console devblk */
2418         sysblk.sysgdev = dev;
2419     }
2420   #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
2421 
2422     return console_initialise();
2423 } /* end function loc3270_init_handler */
2424 
2425 
2426 /*-------------------------------------------------------------------*/
2427 /* QUERY THE 3270 DEVICE DEFINITION                                  */
2428 /*-------------------------------------------------------------------*/
2429 static void
loc3270_query_device(DEVBLK * dev,char ** class,int buflen,char * buffer)2430 loc3270_query_device (DEVBLK *dev, char **class,
2431                 int buflen, char *buffer)
2432 {
2433     BEGIN_DEVICE_CLASS_QUERY( "DSP", dev, class, buflen, buffer );
2434 
2435     if (dev->connected)
2436     {
2437         snprintf (buffer, buflen, "%s",
2438             inet_ntoa(dev->ipaddr));
2439     }
2440     else
2441     {
2442         char  acc[48];
2443 
2444         if (dev->acc_ipaddr || dev->acc_ipmask)
2445         {
2446             char  ip   [16];
2447             char  mask [16];
2448             struct in_addr  xxxx;
2449 
2450             xxxx.s_addr = dev->acc_ipaddr;
2451 
2452             snprintf( ip, sizeof( ip ),
2453                 "%s", inet_ntoa( xxxx ));
2454 
2455             xxxx.s_addr = dev->acc_ipmask;
2456 
2457             snprintf( mask, sizeof( mask ),
2458                 "%s", inet_ntoa( xxxx ));
2459 
2460             snprintf( acc, sizeof( acc ),
2461                 "%s mask %s", ip, mask );
2462         }
2463         else
2464             acc[0] = 0;
2465 
2466         if (dev->filename[0])
2467         {
2468             snprintf(buffer, buflen,
2469                 "GROUP=%s%s%s",
2470                 dev->filename, acc[0] ? " " : "", acc);
2471         }
2472         else
2473         {
2474             if (acc[0])
2475             {
2476                 snprintf(buffer, buflen,
2477                     "* %s", acc);
2478             }
2479             else
2480                 buffer[0] = 0;
2481         }
2482     }
2483 
2484 } /* end function loc3270_query_device */
2485 
2486 
2487 /*-------------------------------------------------------------------*/
2488 /* CLOSE THE 3270 DEVICE HANDLER                                     */
2489 /*-------------------------------------------------------------------*/
2490 static int
loc3270_close_device(DEVBLK * dev)2491 loc3270_close_device ( DEVBLK *dev )
2492 {
2493 
2494   #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
2495     /* Clear the pointer to the SYSG console */
2496     if (dev == sysblk.sysgdev)
2497     {
2498         sysblk.sysgdev = NULL;
2499     }
2500   #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
2501 
2502     console_remove(dev);
2503 
2504     return 0;
2505 } /* end function loc3270_close_device */
2506 
2507 
2508 /*-------------------------------------------------------------------*/
2509 /* 3270 Hercules Suspend/Resume text units                           */
2510 /*-------------------------------------------------------------------*/
2511 #define SR_DEV_3270_BUF          ( SR_DEV_3270 | 0x001 )
2512 #define SR_DEV_3270_EWA          ( SR_DEV_3270 | 0x002 )
2513 #define SR_DEV_3270_POS          ( SR_DEV_3270 | 0x003 )
2514 
2515 /*-------------------------------------------------------------------*/
2516 /* 3270 Hercules Suspend Routine                                     */
2517 /*-------------------------------------------------------------------*/
2518 static int
loc3270_hsuspend(DEVBLK * dev,void * file)2519 loc3270_hsuspend(DEVBLK *dev, void *file)
2520 {
2521     size_t rc, len;
2522     BYTE buf[BUFLEN_3270];
2523 
2524     if (!dev->connected) return 0;
2525     SR_WRITE_VALUE(file, SR_DEV_3270_POS, dev->pos3270, sizeof(dev->pos3270));
2526     SR_WRITE_VALUE(file, SR_DEV_3270_EWA, dev->ewa3270, 1);
2527     obtain_lock(&dev->lock);
2528     rc = solicit_3270_data (dev, R3270_RB);
2529     if (rc == 0 && dev->rlen3270 > 0 && dev->rlen3270 <= BUFLEN_3270)
2530     {
2531         len = dev->rlen3270;
2532         memcpy (buf, dev->buf, len);
2533     }
2534     else
2535         len = 0;
2536     release_lock(&dev->lock);
2537     if (len)
2538         SR_WRITE_BUF(file, SR_DEV_3270_BUF, buf, len);
2539     return 0;
2540 }
2541 
2542 /*-------------------------------------------------------------------*/
2543 /* 3270 Hercules Resume Routine                                      */
2544 /*-------------------------------------------------------------------*/
2545 static int
loc3270_hresume(DEVBLK * dev,void * file)2546 loc3270_hresume(DEVBLK *dev, void *file)
2547 {
2548     size_t rc, key, len, rbuflen = 0, pos = 0;
2549     BYTE *rbuf = NULL, buf[BUFLEN_3270];
2550 
2551     do {
2552         SR_READ_HDR(file, key, len);
2553         switch (key) {
2554         case SR_DEV_3270_POS:
2555             SR_READ_VALUE(file, len, &pos, sizeof(pos));
2556             break;
2557         case SR_DEV_3270_EWA:
2558             SR_READ_VALUE(file, len, &rc, sizeof(rc));
2559             dev->ewa3270 = rc;
2560             break;
2561         case SR_DEV_3270_BUF:
2562             rbuflen = len;
2563             rbuf = malloc(len);
2564             if (rbuf == NULL)
2565             {
2566                 logmsg(_("HHCTE090E %4.4X malloc() failed for resume buf: %s\n"),
2567                        dev->devnum, strerror(errno));
2568                 return 0;
2569             }
2570             SR_READ_BUF(file, rbuf, rbuflen);
2571             break;
2572         default:
2573             SR_READ_SKIP(file, len);
2574             break;
2575         } /* switch (key) */
2576     } while ((key & SR_DEV_MASK) == SR_DEV_3270);
2577 
2578     /* Dequeue any I/O interrupts for this device */
2579     DEQUEUE_IO_INTERRUPT(&dev->ioint);
2580     DEQUEUE_IO_INTERRUPT(&dev->pciioint);
2581     DEQUEUE_IO_INTERRUPT(&dev->attnioint);
2582 
2583     /* Restore the 3270 screen image if connected and buf was provided */
2584     if (dev->connected && rbuf && rbuflen > 3)
2585     {
2586         obtain_lock(&dev->lock);
2587 
2588         /* Construct buffer to send to the 3270 */
2589         len = 0;
2590         buf[len++] = dev->ewa3270 ? R3270_EWA : R3270_EW;
2591         buf[len++] = 0xC2;
2592         memcpy (&buf[len], &rbuf[3], rbuflen - 3);
2593         len += rbuflen - 3;
2594         buf[len++] = O3270_SBA;
2595         buf[len++] = rbuf[1];
2596         buf[len++] = rbuf[2];
2597         buf[len++] = O3270_IC;
2598 
2599         /* Double up any IAC's in the data */
2600         len = double_up_iac (buf, len);
2601 
2602         /* Append telnet EOR marker */
2603         buf[len++] = IAC;
2604         buf[len++] = EOR_MARK;
2605 
2606         /* Restore the 3270 screen */
2607         rc = send_packet(dev->fd, buf, len, "3270 data");
2608 
2609         dev->pos3270 = pos;
2610 
2611         release_lock(&dev->lock);
2612     }
2613 
2614     if (rbuf) free(rbuf);
2615 
2616     return 0;
2617 }
2618 
2619 
2620 /*-------------------------------------------------------------------*/
2621 /* INITIALIZE THE 1052/3215 DEVICE HANDLER                           */
2622 /*-------------------------------------------------------------------*/
2623 static int
constty_init_handler(DEVBLK * dev,int argc,char * argv[])2624 constty_init_handler ( DEVBLK *dev, int argc, char *argv[] )
2625 {
2626     int ac=0;
2627 
2628     /* Indicate that this is a console device */
2629     dev->console = 1;
2630 
2631     /* Set number of sense bytes */
2632     dev->numsense = 1;
2633 
2634     /* Initialize device dependent fields */
2635     dev->keybdrem = 0;
2636 
2637     /* Set length of print buffer */
2638     dev->bufsize = BUFLEN_1052;
2639 
2640     /* Assume we want to prompt */
2641     dev->prompt1052 = 1;
2642 
2643     /* Is there an argument? */
2644     if (argc > 0)
2645     {
2646         /* Look at the argument and set noprompt flag if specified. */
2647         if (strcasecmp(argv[ac], "noprompt") == 0)
2648         {
2649             dev->prompt1052 = 0;
2650             ac++; argc--;
2651         }
2652         // (else it's a group name...)
2653     }
2654 
2655     if(!sscanf(dev->typname,"%hx",&(dev->devtype)))
2656         dev->devtype = 0x1052;
2657 
2658     /* Initialize the device identifier bytes */
2659     dev->devid[0] = 0xFF;
2660     dev->devid[1] = dev->devtype >> 8;
2661     dev->devid[2] = dev->devtype & 0xFF;
2662     dev->devid[3] = 0x00;
2663     dev->devid[4] = dev->devtype >> 8;
2664     dev->devid[5] = dev->devtype & 0xFF;
2665     dev->devid[6] = 0x00;
2666     dev->numdevid = 7;
2667 
2668     dev->filename[0] = 0;
2669     dev->acc_ipaddr = 0;
2670     dev->acc_ipmask = 0;
2671 
2672     if (argc > 0)   // group name?
2673     {
2674         if ('*' == argv[ac][0] && '\0' == argv[ac][1])
2675             ;   // NOP (not really a group name; an '*' is
2676                 // simply used as an argument place holder)
2677         else
2678             strlcpy(dev->filename,argv[ac],sizeof(dev->filename));
2679 
2680         argc--; ac++;
2681         if (argc > 0)   // ip address?
2682         {
2683             if ((dev->acc_ipaddr = inet_addr(argv[ac])) == (in_addr_t)(-1))
2684             {
2685                 logmsg(_("HHCTE011E Device %4.4X: Invalid IP address: %s\n"),
2686                     dev->devnum, argv[ac]);
2687                 return -1;
2688             }
2689             else
2690             {
2691                 argc--; ac++;
2692                 if (argc > 0)   // ip addr mask?
2693                 {
2694                     if ((dev->acc_ipmask = inet_addr(argv[ac])) == (in_addr_t)(-1))
2695                     {
2696                         logmsg(_("HHCTE012E Device %4.4X: Invalid mask value: %s\n"),
2697                             dev->devnum, argv[ac]);
2698                         return -1;
2699                     }
2700                     else
2701                     {
2702                         argc--; ac++;
2703                         if (argc > 0)   // too many args?
2704                         {
2705                             logmsg(_("HHCTE013E Device %4.4X: Extraneous argument(s): %s...\n"),
2706                                 dev->devnum, argv[ac] );
2707                             return -1;
2708                         }
2709                     }
2710                 }
2711                 else
2712                     dev->acc_ipmask = (in_addr_t)(-1);
2713             }
2714         }
2715     }
2716 
2717     return console_initialise();
2718 } /* end function constty_init_handler */
2719 
2720 
2721 /*-------------------------------------------------------------------*/
2722 /* QUERY THE 1052/3215 DEVICE DEFINITION                             */
2723 /*-------------------------------------------------------------------*/
2724 static void
constty_query_device(DEVBLK * dev,char ** class,int buflen,char * buffer)2725 constty_query_device (DEVBLK *dev, char **class,
2726                 int buflen, char *buffer)
2727 {
2728     BEGIN_DEVICE_CLASS_QUERY( "CON", dev, class, buflen, buffer );
2729 
2730     if (dev->connected)
2731     {
2732         snprintf (buffer, buflen, "%s%s",
2733             inet_ntoa(dev->ipaddr),
2734             dev->prompt1052 ? "" : " noprompt");
2735     }
2736     else
2737     {
2738         char  acc[48];
2739 
2740         if (dev->acc_ipaddr || dev->acc_ipmask)
2741         {
2742             char  ip   [16];
2743             char  mask [16];
2744             struct in_addr  xxxx;
2745 
2746             xxxx.s_addr = dev->acc_ipaddr;
2747 
2748             snprintf( ip, sizeof( ip ),
2749                 "%s", inet_ntoa( xxxx ));
2750 
2751             xxxx.s_addr = dev->acc_ipmask;
2752 
2753             snprintf( mask, sizeof( mask ),
2754                 "%s", inet_ntoa( xxxx ));
2755 
2756             snprintf( acc, sizeof( acc ),
2757                 "%s mask %s", ip, mask );
2758         }
2759         else
2760             acc[0] = 0;
2761 
2762         if (dev->filename[0])
2763         {
2764             snprintf(buffer, buflen,
2765                 "GROUP=%s%s%s%s",
2766                 dev->filename,
2767                 !dev->prompt1052 ? " noprompt" : "",
2768                 acc[0] ? " " : "", acc);
2769         }
2770         else
2771         {
2772             if (acc[0])
2773             {
2774                 if (!dev->prompt1052)
2775                     snprintf(buffer, buflen,
2776                         "noprompt %s", acc);
2777                 else
2778                     snprintf(buffer, buflen,
2779                         "* %s", acc);
2780             }
2781             else
2782             {
2783                 if (!dev->prompt1052)
2784                     strlcpy(buffer,"noprompt",buflen);
2785                 else
2786                     buffer[0] = 0;
2787             }
2788         }
2789     }
2790 } /* end function constty_query_device */
2791 
2792 
2793 /*-------------------------------------------------------------------*/
2794 /* CLOSE THE 1052/3215 DEVICE HANDLER                                */
2795 /*-------------------------------------------------------------------*/
2796 static int
constty_close_device(DEVBLK * dev)2797 constty_close_device ( DEVBLK *dev )
2798 {
2799     console_remove(dev);
2800 
2801     return 0;
2802 } /* end function constty_close_device */
2803 
2804 
2805 /*-------------------------------------------------------------------*/
2806 /* SUBROUTINE TO ADVANCE TO NEXT CHAR OR ORDER IN A 3270 DATA STREAM */
2807 /* Input:                                                            */
2808 /*      buf     Buffer containing 3270 data stream                   */
2809 /*      off     Offset in buffer of current character or order       */
2810 /*      pos     Position on screen of current character or order     */
2811 /* Output:                                                           */
2812 /*      off     Offset in buffer of next character or order          */
2813 /*      pos     Position on screen of next character or order        */
2814 /*-------------------------------------------------------------------*/
2815 static void
next_3270_pos(BYTE * buf,int * off,int * pos)2816 next_3270_pos (BYTE *buf, int *off, int *pos)
2817 {
2818 int     i;
2819 
2820     /* Copy the offset and advance the offset by 1 byte */
2821     i = (*off)++;
2822 
2823     /* Advance the offset past the argument bytes and set position */
2824     switch (buf[i]) {
2825 
2826     /* The Repeat to Address order has 3 argument bytes (or in case
2827        of a Graphics Escape 4 bytes) and sets the screen position */
2828             case O3270_RA:
2829 
2830         *off += (buf[i+3] == O3270_GE) ? 4 : 3;
2831                 if ((buf[i+1] & 0xC0) == 0x00)
2832                     *pos = (buf[i+1] << 8) | buf[i+2];
2833                 else
2834                     *pos = ((buf[i+1] & 0x3F) << 6)
2835                                  | (buf[i+2] & 0x3F);
2836         break;
2837 
2838     /* The Start Field Extended and Modify Field orders have
2839        a count byte followed by a variable number of type-
2840        attribute pairs, and advance the screen position by 1 */
2841             case O3270_SFE:
2842             case O3270_MF:
2843 
2844         *off += (1 + 2*buf[i+1]);
2845         (*pos)++;
2846                 break;
2847 
2848     /* The Set Buffer Address and Erase Unprotected to Address
2849        orders have 2 argument bytes and set the screen position */
2850             case O3270_SBA:
2851             case O3270_EUA:
2852 
2853         *off += 2;
2854                 if ((buf[i+1] & 0xC0) == 0x00)
2855                     *pos = (buf[i+1] << 8) | buf[i+2];
2856                 else
2857                     *pos = ((buf[i+1] & 0x3F) << 6)
2858                                  | (buf[i+2] & 0x3F);
2859         break;
2860 
2861     /* The Set Attribute order has 2 argument bytes and
2862        does not change the screen position */
2863             case O3270_SA:
2864 
2865         *off += 2;
2866                 break;
2867 
2868     /* Insert Cursor and Program Tab have no argument
2869        bytes and do not change the screen position */
2870             case O3270_IC:
2871             case O3270_PT:
2872 
2873                 break;
2874 
2875     /* The Start Field and Graphics Escape orders have one
2876        argument byte, and advance the screen position by 1 */
2877             case O3270_SF:
2878             case O3270_GE:
2879 
2880         (*off)++;
2881         (*pos)++;
2882         break;
2883 
2884     /* All other characters advance the screen position by 1 */
2885             default:
2886 
2887                 (*pos)++;
2888                 break;
2889 
2890     } /* end switch */
2891 
2892 } /* end function next_3270_pos */
2893 
2894 
2895 /*-------------------------------------------------------------------*/
2896 /* SUBROUTINE TO FIND A GIVEN SCREEN POSITION IN A 3270 READ BUFFER  */
2897 /* Input:                                                            */
2898 /*      buf     Buffer containing an inbound 3270 data stream        */
2899 /*      size    Number of bytes in buffer                            */
2900 /*      pos     Screen position whose offset in buffer is desired    */
2901 /* Return value:                                                     */
2902 /*      Offset in buffer of the character or order corresponding to  */
2903 /*      the given screen position, or zero if position not found.    */
2904 /*-------------------------------------------------------------------*/
2905 static int
find_buffer_pos(BYTE * buf,int size,int pos)2906 find_buffer_pos (BYTE *buf, int size, int pos)
2907 {
2908 int     wpos;                           /* Current screen position   */
2909 int     woff;                           /* Current offset in buffer  */
2910 
2911     /* Screen position 0 is at offset 3 in the device buffer,
2912        following the AID and cursor address bytes */
2913     wpos = 0;
2914     woff = 3;
2915 
2916     while (woff < size)
2917     {
2918         /* Exit if desired screen position has been reached */
2919         if (wpos >= pos)
2920         {
2921 //          logmsg (_("console: Pos %4.4X reached at %4.4X\n"),
2922 //                  wpos, woff);
2923 
2924 #ifdef FIX_QWS_BUG_FOR_MCS_CONSOLES
2925             /* There is a bug in QWS3270 when used to emulate an
2926                MCS console with EAB.  At position 1680 the Read
2927                Buffer contains two 6-byte SFE orders (12 bytes)
2928                preceding the entry area, whereas MCS expects the
2929                entry area to start 4 bytes after screen position
2930                1680 in the buffer.  The bypass is to add 8 to the
2931                calculated buffer offset if this appears to be an
2932                MCS console read buffer command */
2933             if (pos == 0x0690 && buf[woff] == O3270_SFE
2934                 && buf[woff+6] == O3270_SFE)
2935             {
2936                 woff += 8;
2937 //              logmsg (_("console: Pos %4.4X adjusted to %4.4X\n"),
2938 //                      wpos, woff);
2939         }
2940 #endif /*FIX_QWS_BUG_FOR_MCS_CONSOLES*/
2941 
2942             return woff;
2943         }
2944 
2945         /* Process next character or order, update screen position */
2946         next_3270_pos (buf, &woff, &wpos);
2947 
2948     } /* end while */
2949 
2950     /* Return offset zero if the position cannot be determined */
2951     return 0;
2952 
2953 } /* end function find_buffer_pos */
2954 
2955 
2956 /*-------------------------------------------------------------------*/
2957 /* SUBROUTINE TO UPDATE THE CURRENT SCREEN POSITION                  */
2958 /* Input:                                                            */
2959 /*      pos     Current screen position                              */
2960 /*      buf     Pointer to the byte in the 3270 data stream          */
2961 /*              corresponding to the current screen position         */
2962 /*      size    Number of bytes remaining in buffer                  */
2963 /* Output:                                                           */
2964 /*      pos     Updated screen position after end of buffer          */
2965 /*-------------------------------------------------------------------*/
2966 static void
get_screen_pos(int * pos,BYTE * buf,int size)2967 get_screen_pos (int *pos, BYTE *buf, int size)
2968 {
2969 int     woff = 0;                       /* Current offset in buffer  */
2970 
2971     while (woff < size)
2972     {
2973         /* Process next character or order, update screen position */
2974         next_3270_pos (buf, &woff, pos);
2975 
2976     } /* end while */
2977 
2978 } /* end function get_screen_pos */
2979 
2980 
2981 /*-------------------------------------------------------------------*/
2982 /* EXECUTE A 3270 CHANNEL COMMAND WORD                               */
2983 /*-------------------------------------------------------------------*/
2984 static void
loc3270_execute_ccw(DEVBLK * dev,BYTE code,BYTE flags,BYTE chained,U16 count,BYTE prevcode,int ccwseq,BYTE * iobuf,BYTE * more,BYTE * unitstat,U16 * residual)2985 loc3270_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags,
2986         BYTE chained, U16 count, BYTE prevcode, int ccwseq,
2987         BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual )
2988 {
2989 int             rc;                     /* Return code               */
2990 int             num;                    /* Number of bytes to copy   */
2991 int             len;                    /* Data length               */
2992 int             aid;                    /* First read: AID present   */
2993 U32             off;                    /* Offset in device buffer   */
2994 BYTE            cmd;                    /* tn3270 command code       */
2995 BYTE            buf[BUFLEN_3270];       /* tn3270 write buffer       */
2996 
2997     UNREFERENCED(prevcode);
2998     UNREFERENCED(ccwseq);
2999 
3000     /* Clear the current screen position at start of CCW chain */
3001     if (!chained)
3002         dev->pos3270 = 0;
3003 
3004     /* Unit check with intervention required if no client connected */
3005     if (!dev->connected && !IS_CCW_SENSE(code))
3006     {
3007         dev->sense[0] = SENSE_IR;
3008         /* *unitstat = CSW_CE | CSW_DE | CSW_UC; */
3009         *unitstat = CSW_UC; /* *ISW3274DR* (as per GA23-0218-11 3.1.3.2.2 Table 5-5) */
3010         return;
3011     }
3012 
3013     /* Process depending on CCW opcode */
3014     switch (code) {
3015 
3016     case L3270_NOP:
3017     /*---------------------------------------------------------------*/
3018     /* CONTROL NO-OPERATION                                          */
3019     /*---------------------------------------------------------------*/
3020         /* Reset the buffer address */
3021         dev->pos3270 = 0;
3022 
3023         *unitstat = CSW_CE | CSW_DE;
3024         break;
3025 
3026     case L3270_SELRM:
3027     case L3270_SELRB:
3028     case L3270_SELRMP:
3029     case L3270_SELRBP:
3030     case L3270_SELWRT:
3031     /*---------------------------------------------------------------*/
3032     /* SELECT                                                        */
3033     /*---------------------------------------------------------------*/
3034         /* Reset the buffer address */
3035         dev->pos3270 = 0;
3036 
3037     /*
3038         *residual = 0;
3039     */
3040         *unitstat = CSW_CE | CSW_DE;
3041         break;
3042 
3043     case L3270_EAU:
3044     /*---------------------------------------------------------------*/
3045     /* ERASE ALL UNPROTECTED                                         */
3046     /*---------------------------------------------------------------*/
3047         dev->pos3270 = 0;
3048         cmd = R3270_EAU;
3049         goto write;
3050 
3051     case L3270_WRT:
3052     /*---------------------------------------------------------------*/
3053     /* WRITE                                                         */
3054     /*---------------------------------------------------------------*/
3055         cmd = R3270_WRT;
3056         goto write;
3057 
3058     case L3270_EW:
3059     /*---------------------------------------------------------------*/
3060     /* ERASE/WRITE                                                   */
3061     /*---------------------------------------------------------------*/
3062         dev->pos3270 = 0;
3063         cmd = R3270_EW;
3064         dev->ewa3270 = 0;
3065         goto write;
3066 
3067     case L3270_EWA:
3068     /*---------------------------------------------------------------*/
3069     /* ERASE/WRITE ALTERNATE                                         */
3070     /*---------------------------------------------------------------*/
3071         dev->pos3270 = 0;
3072         cmd = R3270_EWA;
3073         dev->ewa3270 = 1;
3074         goto write;
3075 
3076     case L3270_WSF:
3077     /*---------------------------------------------------------------*/
3078     /* WRITE STRUCTURED FIELD                                        */
3079     /*---------------------------------------------------------------*/
3080         /* Process WSF command if device has extended attributes */
3081         if (dev->eab3270)
3082         {
3083         dev->pos3270 = 0;
3084         cmd = R3270_WSF;
3085             goto write;
3086         }
3087 
3088         /* Operation check, device does not have extended attributes */
3089         dev->sense[0] = SENSE_OC;
3090         *unitstat = CSW_CE | CSW_DE | CSW_UC;
3091         break;
3092 
3093     write:
3094     /*---------------------------------------------------------------*/
3095     /* All write commands, and the EAU control command, come here    */
3096     /*---------------------------------------------------------------*/
3097         /* Initialize the data length */
3098         len = 0;
3099 
3100         /* Calculate number of bytes to move and residual byte count */
3101         num = sizeof(buf) / 2;
3102         num = (count < num) ? count : num;
3103         if(cmd == R3270_EAU)
3104            num = 0;
3105         *residual = count - num;
3106 
3107         /* Move the 3270 command code to the first byte of the buffer
3108            unless data-chained from previous CCW */
3109         if ((chained & CCW_FLAGS_CD) == 0)
3110         {
3111             buf[len++] = cmd;
3112             /* If this is a chained write then we start at the
3113                current buffer address rather then the cursor address.
3114                If the first action the datastream takes is not a
3115                positioning action then insert a SBA to position to
3116                the current buffer address */
3117             if(chained
3118               && cmd == R3270_WRT
3119               && dev->pos3270 != 0
3120               && iobuf[1] != O3270_SBA
3121               && iobuf[1] != O3270_RA
3122               && iobuf[1] != O3270_EUA)
3123             {
3124                 /* Copy the write control character and adjust buffer */
3125                 buf[len++] = *iobuf++; num--;
3126                 /* Insert the SBA order */
3127                 buf[len++] = O3270_SBA;
3128                 if(dev->pos3270 < 4096)
3129                 {
3130                     buf[len++] = sba_code[dev->pos3270 >> 6];
3131                     buf[len++] = sba_code[dev->pos3270 & 0x3F];
3132                 }
3133                 else
3134                 {
3135                     buf[len++] = dev->pos3270 >> 8;
3136                     buf[len++] = dev->pos3270 & 0xFF;
3137                 }
3138             } /* if(iobuf[0] != SBA, RA or EUA) */
3139 
3140             /* Save the screen position at completion of the write.
3141                This is necessary in case a Read Buffer command is chained
3142                from another write or read, this does not apply for the
3143                write structured field command */
3144             if(cmd != R3270_WSF)
3145                 get_screen_pos (&dev->pos3270, iobuf+1, num-1);
3146 
3147         } /* if(!data_chained) */
3148         else /* if(data_chained) */
3149             if(cmd != R3270_WSF)
3150                 get_screen_pos (&dev->pos3270, iobuf, num);
3151 
3152         /* Copy data from channel buffer to device buffer */
3153         memcpy (buf + len, iobuf, num);
3154         len += num;
3155 
3156         /* Double up any IAC bytes in the data */
3157         len = double_up_iac (buf, len);
3158 
3159         /* Append telnet EOR marker at end of data */
3160         if ((flags & CCW_FLAGS_CD) == 0) {
3161             buf[len++] = IAC;
3162             buf[len++] = EOR_MARK;
3163         }
3164 
3165         /* Send the data to the client */
3166         rc = send_packet(dev->fd, buf, len, "3270 data");
3167         if (rc < 0)
3168         {
3169             dev->sense[0] = SENSE_DC;
3170             *unitstat = CSW_CE | CSW_DE | CSW_UC;
3171             break;
3172         }
3173 
3174         /* Return normal status */
3175         *unitstat = CSW_CE | CSW_DE;
3176         break;
3177 
3178     case L3270_RB:
3179     /*---------------------------------------------------------------*/
3180     /* READ BUFFER                                                   */
3181     /*---------------------------------------------------------------*/
3182         /* Obtain the device lock */
3183         obtain_lock (&dev->lock);
3184 
3185         /* AID is only present during the first read */
3186         aid = dev->readpending != 2;
3187 
3188         /* Receive buffer data from client if not data chained */
3189         if ((chained & CCW_FLAGS_CD) == 0)
3190         {
3191             /* Send read buffer command to client and await response */
3192             rc = solicit_3270_data (dev, R3270_RB);
3193             if (rc & CSW_UC)
3194             {
3195                 *unitstat = CSW_CE | CSW_DE | CSW_UC;
3196                 release_lock (&dev->lock);
3197                 break;
3198             }
3199 
3200             /* Set AID in buffer flag */
3201             aid = 1;
3202 
3203             /* Save the AID of the current inbound transmission */
3204             dev->aid3270 = dev->buf[0];
3205             if(dev->pos3270 != 0 && dev->aid3270 != SF3270_AID)
3206             {
3207                 /* Find offset in buffer of current screen position */
3208                 off = find_buffer_pos (dev->buf, dev->rlen3270,
3209                                         dev->pos3270);
3210 
3211                 /* Shift out unwanted characters from buffer */
3212                 num = (dev->rlen3270 > off ? dev->rlen3270 - off : 0);
3213                 memmove (dev->buf + 3, dev->buf + off, num);
3214                 dev->rlen3270 = 3 + num;
3215             }
3216 
3217         } /* end if(!CCW_FLAGS_CD) */
3218 
3219         /* Calculate number of bytes to move and residual byte count */
3220         len = dev->rlen3270;
3221         num = (count < len) ? count : len;
3222         *residual = count - num;
3223         if (count < len) *more = 1;
3224 
3225         /* Save the screen position at completion of the read.
3226            This is necessary in case a Read Buffer command is chained
3227            from another write or read. */
3228         if(dev->aid3270 != SF3270_AID)
3229         {
3230             if(aid)
3231                 get_screen_pos(&dev->pos3270, dev->buf+3, num-3);
3232             else
3233                 get_screen_pos(&dev->pos3270, dev->buf, num);
3234         }
3235 
3236         /* Indicate that the AID bytes have been skipped */
3237         if(dev->readpending == 1)
3238             dev->readpending = 2;
3239 
3240         /* Copy data from device buffer to channel buffer */
3241         memcpy (iobuf, dev->buf, num);
3242 
3243         /* If data chaining is specified, save remaining data */
3244         if ((flags & CCW_FLAGS_CD) && len > count)
3245         {
3246             memmove (dev->buf, dev->buf + count, len - count);
3247             dev->rlen3270 = len - count;
3248         }
3249         else
3250         {
3251             dev->rlen3270 = 0;
3252             dev->readpending = 0;
3253         }
3254 
3255         /* Return normal status */
3256         *unitstat = CSW_CE | CSW_DE;
3257 
3258         /* Release the device lock */
3259         release_lock (&dev->lock);
3260 
3261         /* Signal connection thread to redrive its select loop */
3262         SIGNAL_CONSOLE_THREAD();
3263 
3264         break;
3265 
3266     case L3270_RM:
3267     /*---------------------------------------------------------------*/
3268     /* READ MODIFIED                                                 */
3269     /*---------------------------------------------------------------*/
3270         /* Obtain the device lock */
3271         obtain_lock (&dev->lock);
3272 
3273         /* AID is only present during the first read */
3274         aid = dev->readpending != 2;
3275 
3276         /* If not data chained from previous Read Modified CCW,
3277            and if the connection thread has not already accumulated
3278            a complete Read Modified record in the inbound buffer,
3279            then solicit a Read Modified operation at the client */
3280         if ((chained & CCW_FLAGS_CD) == 0
3281             && !dev->readpending)
3282         {
3283             /* Send read modified command to client, await response */
3284             rc = solicit_3270_data (dev, R3270_RM);
3285             if (rc & CSW_UC)
3286             {
3287                 *unitstat = CSW_CE | CSW_DE | CSW_UC;
3288                 release_lock (&dev->lock);
3289                 break;
3290             }
3291 
3292             /* Set AID in buffer flag */
3293             aid = 1;
3294 
3295             dev->aid3270 = dev->buf[0];
3296             if(dev->pos3270 != 0 && dev->aid3270 != SF3270_AID)
3297             {
3298                 /* Find offset in buffer of current screen position */
3299                 off = find_buffer_pos (dev->buf, dev->rlen3270,
3300                                         dev->pos3270);
3301 
3302                 /* Shift out unwanted characters from buffer */
3303                 num = (dev->rlen3270 > off ? dev->rlen3270 - off : 0);
3304                 memmove (dev->buf + 3, dev->buf + off, num);
3305                 dev->rlen3270 = 3 + num;
3306             }
3307 
3308         } /* end if(!CCW_FLAGS_CD) */
3309 
3310         /* Calculate number of bytes to move and residual byte count */
3311         len = dev->rlen3270;
3312         num = (count < len) ? count : len;
3313         *residual = count - num;
3314         if (count < len) *more = 1;
3315 
3316         /* Save the screen position at completion of the read.
3317            This is necessary in case a Read Buffer command is chained
3318            from another write or read. */
3319         if(dev->aid3270 != SF3270_AID)
3320         {
3321             if(aid)
3322                 get_screen_pos(&dev->pos3270, dev->buf+3, num-3);
3323             else
3324                 get_screen_pos(&dev->pos3270, dev->buf, num);
3325         }
3326 
3327         /* Indicate that the AID bytes have been skipped */
3328         if(dev->readpending == 1)
3329             dev->readpending = 2;
3330 
3331         /* Copy data from device buffer to channel buffer */
3332         memcpy (iobuf, dev->buf, num);
3333 
3334         /* If data chaining is specified, save remaining data */
3335         if ((flags & CCW_FLAGS_CD) && len > count)
3336         {
3337             memmove (dev->buf, dev->buf + count, len - count);
3338             dev->rlen3270 = len - count;
3339         }
3340         else
3341         {
3342             dev->rlen3270 = 0;
3343             dev->readpending = 0;
3344         }
3345 
3346         /* Set normal status */
3347         *unitstat = CSW_CE | CSW_DE;
3348 
3349         /* Release the device lock */
3350         release_lock (&dev->lock);
3351 
3352         /* Signal connection thread to redrive its select loop */
3353         SIGNAL_CONSOLE_THREAD();
3354 
3355         break;
3356 
3357     case L3270_SENSE:
3358     /*---------------------------------------------------------------*/
3359     /* SENSE                                                         */
3360     /*---------------------------------------------------------------*/
3361         /* Calculate residual byte count */
3362         num = (count < dev->numsense) ? count : dev->numsense;
3363         *residual = count - num;
3364         if (count < dev->numsense) *more = 1;
3365 
3366         /* Copy device sense bytes to channel I/O buffer */
3367         memcpy (iobuf, dev->sense, num);
3368 
3369         /* Clear the device sense bytes */
3370         memset (dev->sense, 0, sizeof(dev->sense));
3371 
3372         /* Reset the buffer address */
3373         dev->pos3270 = 0;
3374 
3375         /* Return unit status */
3376         *unitstat = CSW_CE | CSW_DE;
3377         break;
3378 
3379     case L3270_SENSEID:
3380     /*---------------------------------------------------------------*/
3381     /* SENSE ID                                                      */
3382     /*---------------------------------------------------------------*/
3383         /* Calculate residual byte count */
3384         num = (count < dev->numdevid) ? count : dev->numdevid;
3385         *residual = count - num;
3386         if (count < dev->numdevid) *more = 1;
3387 
3388         /* Copy device identifier bytes to channel I/O buffer */
3389         memcpy (iobuf, dev->devid, num);
3390 
3391         /* Reset the buffer address */
3392         dev->pos3270 = 0;
3393 
3394         /* Return unit status */
3395         *unitstat = CSW_CE | CSW_DE;
3396         break;
3397 
3398     default:
3399     /*---------------------------------------------------------------*/
3400     /* INVALID OPERATION                                             */
3401     /*---------------------------------------------------------------*/
3402         /* Set command reject sense byte, and unit check status */
3403         dev->sense[0] = SENSE_CR;
3404         *unitstat = CSW_CE | CSW_DE | CSW_UC;
3405 
3406     } /* end switch(code) */
3407 
3408 } /* end function loc3270_execute_ccw */
3409 
3410 
3411 /*-------------------------------------------------------------------*/
3412 /* EXECUTE A 1052/3215 CHANNEL COMMAND WORD                          */
3413 /*-------------------------------------------------------------------*/
3414 static void
constty_execute_ccw(DEVBLK * dev,BYTE code,BYTE flags,BYTE chained,U16 count,BYTE prevcode,int ccwseq,BYTE * iobuf,BYTE * more,BYTE * unitstat,U16 * residual)3415 constty_execute_ccw ( DEVBLK *dev, BYTE code, BYTE flags,
3416         BYTE chained, U16 count, BYTE prevcode, int ccwseq,
3417         BYTE *iobuf, BYTE *more, BYTE *unitstat, U16 *residual )
3418 {
3419 int     rc;                             /* Return code               */
3420 int     len;                            /* Length of data            */
3421 int     num;                            /* Number of bytes to move   */
3422 BYTE    c;                              /* Print character           */
3423 BYTE    stat;                           /* Unit status               */
3424 
3425     UNREFERENCED(chained);
3426     UNREFERENCED(prevcode);
3427     UNREFERENCED(ccwseq);
3428 
3429     /* Unit check with intervention required if no client connected */
3430     if (dev->connected == 0 && !IS_CCW_SENSE(code))
3431     {
3432         dev->sense[0] = SENSE_IR;
3433         *unitstat = CSW_UC;
3434         return;
3435     }
3436 
3437     /* Process depending on CCW opcode */
3438     switch (code) {
3439 
3440     case 0x01:
3441     /*---------------------------------------------------------------*/
3442     /* WRITE NO CARRIER RETURN                                       */
3443     /*---------------------------------------------------------------*/
3444 
3445     case 0x09:
3446     /*---------------------------------------------------------------*/
3447     /* WRITE AUTO CARRIER RETURN                                     */
3448     /*---------------------------------------------------------------*/
3449 
3450         /* Calculate number of bytes to write and set residual count */
3451         num = (count < BUFLEN_1052) ? count : BUFLEN_1052;
3452         *residual = count - num;
3453 
3454         /* Translate data in channel buffer to ASCII */
3455         for (len = 0; len < num; len++)
3456         {
3457             c = guest_to_host(iobuf[len]);
3458             if (!isprint(c) && c != 0x0a && c != 0x0d) c = SPACE;
3459             iobuf[len] = c;
3460         } /* end for(len) */
3461 
3462         ASSERT(len == num);
3463 
3464         /* Perform end of record processing if not data-chaining */
3465         if ((flags & CCW_FLAGS_CD) == 0)
3466         {
3467             /* Append carriage return and newline if required */
3468             if (code == 0x09)
3469             {
3470                 if (len < BUFLEN_1052)
3471                     iobuf[len++] = '\r';
3472 
3473                 if (len < BUFLEN_1052)
3474                     iobuf[len++] = '\n';
3475             }
3476         } /* end if(!data-chaining) */
3477 
3478         /* Send the data to the client */
3479         rc = send_packet (dev->fd, iobuf, len, NULL);
3480         if (rc < 0)
3481         {
3482             dev->sense[0] = SENSE_EC;
3483             *unitstat = CSW_CE | CSW_DE | CSW_UC;
3484             break;
3485         }
3486 
3487         /* Return normal status */
3488         *unitstat = CSW_CE | CSW_DE;
3489         break;
3490 
3491     case 0x03:
3492     /*---------------------------------------------------------------*/
3493     /* CONTROL NO-OPERATION                                          */
3494     /*---------------------------------------------------------------*/
3495         *unitstat = CSW_CE | CSW_DE;
3496         break;
3497 
3498     case 0x0A:
3499     /*---------------------------------------------------------------*/
3500     /* READ INQUIRY                                                  */
3501     /*---------------------------------------------------------------*/
3502 
3503         /* Solicit console input if no data in the device buffer */
3504         if (!dev->keybdrem)
3505         {
3506             /* Display prompting message on console if allowed */
3507             if (dev->prompt1052)
3508             {
3509                 snprintf ((char *)dev->buf, dev->bufsize,
3510                         _("HHCTE006A Enter input for console device %4.4X\n"),
3511                         dev->devnum);
3512                 len = strlen((char *)dev->buf);
3513                 rc = send_packet (dev->fd, dev->buf, len, NULL);
3514                 if (rc < 0)
3515                 {
3516                     dev->sense[0] = SENSE_EC;
3517                     *unitstat = CSW_CE | CSW_DE | CSW_UC;
3518                     break;
3519                 }
3520             }
3521 
3522             /* Accumulate client input data into device buffer */
3523             while (1) {
3524 
3525                 /* Receive client data and increment dev->keybdrem */
3526                 stat = recv_1052_data (dev);
3527 
3528                 /* Exit if error or end of line */
3529                 if (stat != 0)
3530                     break;
3531 
3532             } /* end while */
3533 
3534             /* Exit if error status */
3535             if (stat != CSW_ATTN)
3536             {
3537                 *unitstat = (CSW_CE | CSW_DE) | (stat & ~CSW_ATTN);
3538                 break;
3539             }
3540 
3541         }
3542 
3543         /* Calculate number of bytes to move and residual byte count */
3544         len = dev->keybdrem;
3545         num = (count < len) ? count : len;
3546         *residual = count - num;
3547         if (count < len) *more = 1;
3548 
3549         /* Copy data from device buffer to channel buffer */
3550         memcpy (iobuf, dev->buf, num);
3551 
3552         /* If data chaining is specified, save remaining data */
3553         if ((flags & CCW_FLAGS_CD) && len > count)
3554         {
3555             memmove (dev->buf, dev->buf + count, len - count);
3556             dev->keybdrem = len - count;
3557         }
3558         else
3559         {
3560             dev->keybdrem = 0;
3561         }
3562 
3563         /* Return normal status */
3564         *unitstat = CSW_CE | CSW_DE;
3565         break;
3566 
3567     case 0x0B:
3568     /*---------------------------------------------------------------*/
3569     /* AUDIBLE ALARM                                                 */
3570     /*---------------------------------------------------------------*/
3571         rc = send_packet (dev->fd, (BYTE *)"\a", 1, NULL);
3572     /*
3573         *residual = 0;
3574     */
3575         *unitstat = CSW_CE | CSW_DE;
3576         break;
3577 
3578     case 0x04:
3579     /*---------------------------------------------------------------*/
3580     /* SENSE                                                         */
3581     /*---------------------------------------------------------------*/
3582         /* Calculate residual byte count */
3583         num = (count < dev->numsense) ? count : dev->numsense;
3584         *residual = count - num;
3585         if (count < dev->numsense) *more = 1;
3586 
3587         /* Copy device sense bytes to channel I/O buffer */
3588         memcpy (iobuf, dev->sense, num);
3589 
3590         /* Clear the device sense bytes */
3591         memset (dev->sense, 0, sizeof(dev->sense));
3592 
3593         /* Return unit status */
3594         *unitstat = CSW_CE | CSW_DE;
3595         break;
3596 
3597     case 0xE4:
3598     /*---------------------------------------------------------------*/
3599     /* SENSE ID                                                      */
3600     /*---------------------------------------------------------------*/
3601         /* Calculate residual byte count */
3602         num = (count < dev->numdevid) ? count : dev->numdevid;
3603         *residual = count - num;
3604         if (count < dev->numdevid) *more = 1;
3605 
3606         /* Copy device identifier bytes to channel I/O buffer */
3607         memcpy (iobuf, dev->devid, num);
3608 
3609         /* Return unit status */
3610         *unitstat = CSW_CE | CSW_DE;
3611         break;
3612 
3613     default:
3614     /*---------------------------------------------------------------*/
3615     /* INVALID OPERATION                                             */
3616     /*---------------------------------------------------------------*/
3617         /* Set command reject sense byte, and unit check status */
3618         dev->sense[0] = SENSE_CR;
3619         *unitstat = CSW_CE | CSW_DE | CSW_UC;
3620 
3621     } /* end switch(code) */
3622 
3623 } /* end function constty_execute_ccw */
3624 
3625 #if defined(OPTION_DYNAMIC_LOAD)
3626 static
3627 #endif
3628 DEVHND constty_device_hndinfo = {
3629         &constty_init_handler,         /* Device Initialisation      */
3630         &constty_execute_ccw,          /* Device CCW execute         */
3631         &constty_close_device,         /* Device Close               */
3632         &constty_query_device,         /* Device Query               */
3633         NULL,                          /* Device Start channel pgm   */
3634         NULL,                          /* Device End channel pgm     */
3635         NULL,                          /* Device Resume channel pgm  */
3636         NULL,                          /* Device Suspend channel pgm */
3637         NULL,                          /* Device Read                */
3638         NULL,                          /* Device Write               */
3639         NULL,                          /* Device Query used          */
3640         NULL,                          /* Device Reserve             */
3641         NULL,                          /* Device Release             */
3642         NULL,                          /* Device Attention           */
3643         constty_immed,                 /* Immediate CCW Codes        */
3644         NULL,                          /* Signal Adapter Input       */
3645         NULL,                          /* Signal Adapter Output      */
3646         NULL,                          /* Hercules suspend           */
3647         NULL                           /* Hercules resume            */
3648 };
3649 
3650 /* Libtool static name colision resolution */
3651 /* note : lt_dlopen will look for symbol & modulename_LTX_symbol */
3652 #if !defined(HDL_BUILD_SHARED) && defined(HDL_USE_LIBTOOL)
3653 #define hdl_ddev hdt3270_LTX_hdl_ddev
3654 #define hdl_depc hdt3270_LTX_hdl_depc
3655 #define hdl_reso hdt3270_LTX_hdl_reso
3656 #define hdl_init hdt3270_LTX_hdl_init
3657 #define hdl_fini hdt3270_LTX_hdl_fini
3658 #endif
3659 
3660 
3661 #if defined(OPTION_DYNAMIC_LOAD)
3662 static
3663 #endif
3664 DEVHND loc3270_device_hndinfo = {
3665         &loc3270_init_handler,         /* Device Initialisation      */
3666         &loc3270_execute_ccw,          /* Device CCW execute         */
3667         &loc3270_close_device,         /* Device Close               */
3668         &loc3270_query_device,         /* Device Query               */
3669         NULL,                          /* Device Start channel pgm   */
3670         NULL,                          /* Device End channel pgm     */
3671         NULL,                          /* Device Resume channel pgm  */
3672         NULL,                          /* Device Suspend channel pgm */
3673         NULL,                          /* Device Read                */
3674         NULL,                          /* Device Write               */
3675         NULL,                          /* Device Query used          */
3676         NULL,                          /* Device Reserve             */
3677         NULL,                          /* Device Release             */
3678         NULL,                          /* Device Attention           */
3679         loc3270_immed,                 /* Immediate CCW Codes        */
3680         NULL,                          /* Signal Adapter Input       */
3681         NULL,                          /* Signal Adapter Output      */
3682         &loc3270_hsuspend,             /* Hercules suspend           */
3683         &loc3270_hresume               /* Hercules resume            */
3684 };
3685 
3686 
3687 #if defined(OPTION_DYNAMIC_LOAD)
3688 HDL_DEPENDENCY_SECTION;
3689 {
3690      HDL_DEPENDENCY(HERCULES);
3691      HDL_DEPENDENCY(DEVBLK);
3692      HDL_DEPENDENCY(SYSBLK);
3693 }
3694 END_DEPENDENCY_SECTION
3695 
3696 
3697 #if defined(WIN32) && !defined(HDL_USE_LIBTOOL) && !defined(_MSVC_)
3698   #undef sysblk
3699   #undef config_cnslport
3700   HDL_RESOLVER_SECTION;
3701   {
3702     HDL_RESOLVE_PTRVAR( psysblk, sysblk );
3703     HDL_RESOLVE( config_cnslport );
3704   }
3705   END_RESOLVER_SECTION
3706 #endif
3707 
3708 
3709 HDL_DEVICE_SECTION
3710 {
3711     HDL_DEVICE(1052, constty_device_hndinfo );
3712     HDL_DEVICE(3215, constty_device_hndinfo );
3713     HDL_DEVICE(3270, loc3270_device_hndinfo );
3714     HDL_DEVICE(3287, loc3270_device_hndinfo );
3715 
3716   #if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
3717     HDL_DEVICE(SYSG, loc3270_device_hndinfo );
3718   #endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
3719 }
3720 END_DEVICE_SECTION
3721 #endif
3722