diff --git a/Hercules_VS2008.vcproj b/Hercules_VS2008.vcproj
index 4b4767002..aefdcfc5a 100644
--- a/Hercules_VS2008.vcproj
+++ b/Hercules_VS2008.vcproj
@@ -1131,6 +1131,10 @@
RelativePath=".\strsignal.c"
>
+
+
@@ -1163,6 +1167,10 @@
RelativePath=".\w32util.c"
>
+
+
@@ -1511,6 +1519,10 @@
RelativePath=".\targetver.h"
>
+
+
@@ -1535,6 +1547,10 @@
RelativePath=".\w32util.h"
>
+
+
+
+
diff --git a/Hercules_VS2015.vcxproj b/Hercules_VS2015.vcxproj
index d9265f7f3..96da5fd18 100644
--- a/Hercules_VS2015.vcxproj
+++ b/Hercules_VS2015.vcxproj
@@ -444,6 +444,7 @@
+
@@ -455,6 +456,7 @@
+
@@ -692,6 +694,7 @@
+
@@ -1111,6 +1114,7 @@
+
@@ -1123,6 +1127,7 @@
+
@@ -1374,4 +1379,4 @@
-
\ No newline at end of file
+
diff --git a/Hercules_VS2015.vcxproj.filters b/Hercules_VS2015.vcxproj.filters
index 3b627e678..d95e8cdb2 100644
--- a/Hercules_VS2015.vcxproj.filters
+++ b/Hercules_VS2015.vcxproj.filters
@@ -738,6 +738,9 @@
Source Files\Hercules\Emulation\Source Files
+
+ Source Files\Hercules\Emulation\Source Files
+
Source Files\Hercules\Emulation\Source Files
@@ -762,6 +765,9 @@
Source Files\Hercules\Emulation\Source Files
+
+ Source Files\Hercules\Emulation\Source Files
+
Source Files\Hercules\Emulation\Source Files
@@ -1001,6 +1007,9 @@
Other Files\DOC\README
+
+ Other Files\DOC\README
+
Other Files\DOC\README
@@ -2701,6 +2710,9 @@
Source Files\Hercules\Emulation\Header Files
+
+ Source Files\Hercules\Emulation\Header Files
+
Source Files\Hercules\Emulation\Header Files
@@ -2716,6 +2728,9 @@
Source Files\Hercules\Emulation\Header Files
+
+ Source Files\Hercules\Emulation\Header Files
+
Source Files\Hercules\ExtPkgs\decNumber\include
@@ -3481,4 +3496,4 @@
Resource Files
-
\ No newline at end of file
+
diff --git a/Hercules_VS2017.vcxproj b/Hercules_VS2017.vcxproj
index 9966a93ce..f04b69f93 100644
--- a/Hercules_VS2017.vcxproj
+++ b/Hercules_VS2017.vcxproj
@@ -443,6 +443,7 @@
+
@@ -455,6 +456,7 @@
+
@@ -692,6 +694,7 @@
+
@@ -1111,6 +1114,7 @@
+
@@ -1123,6 +1127,7 @@
+
@@ -1374,4 +1379,4 @@
-
\ No newline at end of file
+
diff --git a/Hercules_VS2017.vcxproj.filters b/Hercules_VS2017.vcxproj.filters
index 3b627e678..d95e8cdb2 100644
--- a/Hercules_VS2017.vcxproj.filters
+++ b/Hercules_VS2017.vcxproj.filters
@@ -738,6 +738,9 @@
Source Files\Hercules\Emulation\Source Files
+
+ Source Files\Hercules\Emulation\Source Files
+
Source Files\Hercules\Emulation\Source Files
@@ -762,6 +765,9 @@
Source Files\Hercules\Emulation\Source Files
+
+ Source Files\Hercules\Emulation\Source Files
+
Source Files\Hercules\Emulation\Source Files
@@ -1001,6 +1007,9 @@
Other Files\DOC\README
+
+ Other Files\DOC\README
+
Other Files\DOC\README
@@ -2701,6 +2710,9 @@
Source Files\Hercules\Emulation\Header Files
+
+ Source Files\Hercules\Emulation\Header Files
+
Source Files\Hercules\Emulation\Header Files
@@ -2716,6 +2728,9 @@
Source Files\Hercules\Emulation\Header Files
+
+ Source Files\Hercules\Emulation\Header Files
+
Source Files\Hercules\ExtPkgs\decNumber\include
@@ -3481,4 +3496,4 @@
Resource Files
-
\ No newline at end of file
+
diff --git a/Makefile.am b/Makefile.am
index 9ad4f5e08..177d12efc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -472,12 +472,14 @@ libherc_la_SOURCES = \
sr.c \
stack.c \
strsignal.c \
+ tcpip.c \
timer.c \
trace.c \
transact.c \
vector.c \
vm.c \
vmd250.c \
+ x75.c \
xstore.c \
$(DYNSRC)
@@ -797,6 +799,7 @@ EXTRA_DIST = \
README.SOFTFLOAT \
README.SUN \
README.TAPE \
+ README.TCPIP \
README.VMFPLC2 \
README.TELNET \
README.WIN64 \
@@ -929,6 +932,7 @@ noinst_HEADERS = \
stfl.h \
tapedev.h \
targetver.h \
+ tcpip.h \
tt32api.h \
tt32if.h \
tuntap.h \
@@ -940,6 +944,7 @@ noinst_HEADERS = \
w32mtio.h \
w32stape.h \
w32util.h \
+ x75.h \
zfcp.h
###############################################################################
diff --git a/Makefile.in b/Makefile.in
index 28603e719..da09abf99 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -218,8 +218,8 @@ am_libherc_la_OBJECTS = _archdep_templ.lo archlvl.lo assist.lo \
httpserv.lo ieee.lo impl.lo io.lo ipl.lo loadmem.lo \
loadparm.lo losc.lo machchk.lo opcode.lo panel.lo pfpo.lo \
plo.lo qdio.lo scedasd.lo scescsi.lo script.lo service.lo \
- sie.lo sr.lo stack.lo strsignal.lo timer.lo trace.lo \
- transact.lo vector.lo vm.lo vmd250.lo xstore.lo \
+ sie.lo sr.lo stack.lo strsignal.lo tcpip.lo timer.lo trace.lo \
+ transact.lo vector.lo vm.lo vmd250.lo x75.lo xstore.lo \
$(am__objects_1)
libherc_la_OBJECTS = $(am_libherc_la_OBJECTS)
libherc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -1103,12 +1103,14 @@ libherc_la_SOURCES = \
sr.c \
stack.c \
strsignal.c \
+ tcpip.c \
timer.c \
trace.c \
transact.c \
vector.c \
vm.c \
vmd250.c \
+ x75.c \
xstore.c \
$(DYNSRC)
@@ -1387,6 +1389,7 @@ EXTRA_DIST = \
README.SOFTFLOAT \
README.SUN \
README.TAPE \
+ README.TCPIP \
README.VMFPLC2 \
README.TELNET \
README.WIN64 \
@@ -1519,6 +1522,7 @@ noinst_HEADERS = \
stfl.h \
tapedev.h \
targetver.h \
+ tcpip.h \
tt32api.h \
tt32if.h \
tuntap.h \
@@ -1530,6 +1534,7 @@ noinst_HEADERS = \
w32mtio.h \
w32stape.h \
w32util.h \
+ x75.h \
zfcp.h
all: config.h
@@ -2019,6 +2024,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapedev.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapemap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tapesplt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcpip.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transact.Plo@am__quote@
@@ -2028,6 +2034,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmd250.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmfplc2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x75.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfcp.Plo@am__quote@
diff --git a/README.TCPIP b/README.TCPIP
new file mode 100644
index 000000000..e26a19ff0
--- /dev/null
+++ b/README.TCPIP
@@ -0,0 +1,94 @@
+Guest Access To Host IP Stack - The TCPIP (X'75') Instruction
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+Introduction
+============
+
+Around 2002 Jason Winter developed a Hercules extension allowing the guest OS to access the
+IP stack of the host OS by means of a special instruction that does not exist on real
+S/3x0, ESA/390 or z/Architecture hardware. The operation is in RX format, its operation
+code is X'75':
+
+75rxbddd - TCPIP R1,D2(X2,B2) R1=GPR 0-15, B2=GPR 5-13, X2=GPR 0,5-13
+
+As opposed to "classic" instructions the TCPIP (X'75') instruction preserves a state
+between calls, an essential requirement to transfer IP traffic back and forth between the
+host and the guest. Due to this fact, setting up for native execution of the instruction is
+complex.
+
+To avoid having application programmers go through this complexity, at the time of this
+writing two higher-level interfaces are available, allowing easy and standardized access to
+the functionality provided by the TCPIP instruction:
+
+- A socket API in Jason's JCC-Library, which provides the well-known C socket
+ programming functions. See the JCC-Library help in the JCC distribution (found in
+ TK4-.JASON.JCC.ZIP on TK4- systems) for a description of the functions available.
+
+- TCP/IP for MVS 3.8 Assembler by Shelby Beach, a programming interface that is source
+ code compatible to IBM's well-known EZASMI API. A comprehensive documentation of all
+ available functions is part of the installer found at TK4-.SHELBY.EZASMI.V100.ZIP on
+ TK4- systems.
+
+Caution: The TCPIP instruction gives a guest program the very same access to the host's IP
+-------- stack that the host process running the Hercules instance has. Allowing every
+ guest program this type of access may be undesirable, particularly when the
+ Hercules process runs using elevated privileges. In addition, one guest program
+ can easily interfere with IP communications of any other guest program by
+ hijacking the other program's socket identifiers. In sum, a malicious user with
+ access to the TCPIP instruction can severely compromise the guest's and the
+ host's integrity. A problem state instruction with this type of capabilities
+ clearly does not comply with parts specifications of the architectures emulated
+ by Hercules.
+
+ To allow users to overcome these weaknesses of the TCPIP instruction, its
+ implementation on SDL Hyperion comes in two flavors: As a supervisor state and as
+ a problem state instruction, both of which are functionality wise identical.
+ Enabling the TCPIP instruction will default to the supervisor state instruction.
+ That way, only programs running in supervisor state can execute the instruction,
+ which is considered being compliant with the emulated architectures.
+
+ Note that both TCPIP APIs currently existing for S/370 operating systems (C
+ socket library and EZASMI) rely on the instruction being available in problem
+ state, which is not architecture compliant. Using the problem state flavor of the
+ instruction is at the user's sole risk.
+
+ Note also, that currently no software exists that would be able to make use of
+ the supervisor state flavor of the TCPIP instruction in a controlled way.
+
+
+Usage
+=====
+
+Availability and flavor of the TCPIP instruction are controlled by three elements:
+
+1. The compile time FEATURE_TCPIP_EXTENSION definition: To allow enabling of the TCPIP
+ instruction, the featxxx.h header file corresponding to the relevant architecture(s)
+ must contain the statement
+
+ #define FEATURE_TCPIP_EXTENSION
+
+ As shipped, SDL Hyperion has this feature defined for the S/370 architecture
+ (feat370.h) only.
+
+2. By default, the TCPIP instruction is at run time disabled, regardless whether the
+ compile time FEATURE_TCPIP_EXTENSION was defined or not. If FEATURE_TCPIP_EXTENSION
+ was defined for the architecture being currently in use, the supervisor state flavor
+ of the TCPIP instruction can be enabled by issuing the command
+
+ facility enable HERC_TCPIP_EXTENSION
+
+ before IPLing the operating system.
+
+3. If the problem state flavor of the TCPIP instruction is desired, after having
+ enabled the supervisor state flavor as described above, the command
+
+ facility enable HERC_TCPIP_PROB_STATE
+
+ must be issued before IPLing the operating system.
+
+
+Copyright
+=========
+
+See the comment headers of the x75.c and tcpip.c programs for copyright information.
diff --git a/facility.c b/facility.c
index 8f44649d0..278fdabcd 100644
--- a/facility.c
+++ b/facility.c
@@ -605,6 +605,11 @@ FT( Z390, Z390, NONE, HERC_SVS )
FT( MALL, NONE, NONE, HERC_VIRTUAL_MACHINE )
#endif
+#if defined( FEATURE_TCPIP_EXTENSION )
+FT( MALL, NONE, NONE, HERC_TCPIP_EXTENSION )
+FT( MALL, NONE, NONE, HERC_TCPIP_PROB_STATE )
+#endif
+
};
/*-------------------------------------------------------------------*/
@@ -722,6 +727,7 @@ static void instr146 ( int arch, bool enable );
static void hercmvcin( int arch, bool enable );
static void hercsvs ( int arch, bool enable );
static void herc37X ( int arch, bool enable );
+static void herctcp ( int arch, bool enable );
/*-------------------------------------------------------------------*/
/* The ACTUAL facilities table, initialized by init_facilities_lists */
@@ -841,6 +847,8 @@ FT2( NULL, NULL, HERC_QEBSM, "Hercules QDIO Enhanced B
FT2( NULL, NULL, HERC_SIGP_SETARCH_S370, "Hercules SIGP Set Architecture S/370 Support" )
FT2( NULL, hercsvs, HERC_SVS, "Hercules SVS Set Vector Summary Instruction Support" )
FT2( NULL, NULL, HERC_VIRTUAL_MACHINE, "Hercules Emulate Virtual Machine Support" )
+FT2( NULL, herctcp, HERC_TCPIP_EXTENSION, "Hercules Access Host TCP/IP Stack Through X'75' Instruction" )
+FT2( NULL, NULL, HERC_TCPIP_PROB_STATE, "Hercules Enable X'75' As Problem State Instruction" )
};
/*-------------------------------------------------------------------*/
@@ -3167,6 +3175,14 @@ BEG_DIS_FAC_INS_FUNC( herc37X )
}
END_DIS_FAC_INS_FUNC()
+/*-------------------------------------------------------------------*/
+
+BEG_DIS_FAC_INS_FUNC( herctcp )
+{
+ DIS_FAC_INS( 75, "TCPIP 75 TCPIP" );
+}
+END_DIS_FAC_INS_FUNC()
+
/*-------------------------------------------------------------------*/
/* Special handling for HERC_370_EXTENSION Pseudo-Facility */
/*-------------------------------------------------------------------*/
diff --git a/feat370.h b/feat370.h
index 85f1e6d68..c7ba7ed9b 100644
--- a/feat370.h
+++ b/feat370.h
@@ -47,6 +47,7 @@
#define FEATURE_SEGMENT_PROTECTION
#define FEATURE_TEST_BLOCK
#define FEATURE_VM_BLOCKIO
+#define FEATURE_TCPIP_EXTENSION
/*-------------------------------------------------------------------*/
/* "Hercules S/370 Instruction Extension Facility" */
diff --git a/featall.h b/featall.h
index 6e0677611..490ef5bfa 100644
--- a/featall.h
+++ b/featall.h
@@ -328,5 +328,6 @@
#undef FEATURE_VIRTUAL_ARCHITECTURE_LEVEL
#undef FEATURE_VM_BLOCKIO
#undef FEATURE_WAITSTATE_ASSIST
+#undef FEATURE_TCPIP_EXTENSION
/* end of FEATALL.H */
diff --git a/featchk.h b/featchk.h
index e55345f08..0dcb2ceab 100644
--- a/featchk.h
+++ b/featchk.h
@@ -547,6 +547,10 @@
#define _FEATURE_WAITSTATE_ASSIST
#endif
+#if defined( FEATURE_TCPIP_EXTENSION )
+ #define _FEATURE_TCPIP_EXTENSION
+#endif
+
/*-------------------------------------------------------------------*/
/* PROGRAMMING NOTE */
/*-------------------------------------------------------------------*/
diff --git a/msvc.makefile.includes/OBJ_CODE.msvc b/msvc.makefile.includes/OBJ_CODE.msvc
index b48abf30d..1931b870c 100644
--- a/msvc.makefile.includes/OBJ_CODE.msvc
+++ b/msvc.makefile.includes/OBJ_CODE.msvc
@@ -140,10 +140,12 @@ hengine_OBJ = \
$(O)sie.obj \
$(O)sr.obj \
$(O)stack.obj \
+ $(O)tcpip.obj \
$(O)timer.obj \
$(O)trace.obj \
$(O)transact.obj \
$(O)vector.obj \
$(O)vm.obj \
$(O)vmd250.obj \
+ $(O)x75.obj \
$(O)xstore.obj
diff --git a/opcode.c b/opcode.c
index 8fc05d1c3..d71ec1f4c 100644
--- a/opcode.c
+++ b/opcode.c
@@ -1235,6 +1235,10 @@ DISABLE_GCC_UNUSED_FUNCTION_WARNING;
UNDEF_INST( set_vector_summary )
#endif
+#if !defined( FEATURE_TCPIP_EXTENSION )
+ UNDEF_INST( tcpip )
+#endif
+
/*----------------------------------------------------------------------------*/
/* The following execute_xxxx routines can be optimized by the compiler to */
/* an indexed jump, leaving the stack frame untouched as the called routine */
@@ -2059,7 +2063,7 @@ static INSTR_FUNC opcode_table[256][NUM_INSTR_TAB_PTRS] =
/*72*/ GENx___x___x___ ,
/*73*/ GENx___x___x___ ,
/*74*/ GENx___x___x___ ,
- /*75*/ GENx___x___x___ ,
+ /*75*/ GENx370x390x900 (tcpip,RX,"TCPIP"),
/*76*/ GENx___x___x___ ,
/*77*/ GENx___x___x___ ,
/*78*/ GENx370x390x900 (load_float_short,RX,"LE"),
diff --git a/opcode.h b/opcode.h
index f2ea7efa7..4792e3cef 100644
--- a/opcode.h
+++ b/opcode.h
@@ -4475,6 +4475,10 @@ DEF_INST( search_string );
DEF_INST( branch_in_subspace_group );
#endif
+#if defined( FEATURE_TCPIP_EXTENSION )
+DEF_INST( tcpip );
+#endif
+
/*-------------------------------------------------------------------*/
/* Instructions NOT associated with ANY facility or feature */
/*-------------------------------------------------------------------*/
diff --git a/stfl.h b/stfl.h
index 9e647bebc..76dab6200 100644
--- a/stfl.h
+++ b/stfl.h
@@ -337,8 +337,10 @@
#define STFL_HERC_SIGP_SETARCH_S370 ( STFL_HERC_FIRST_BIT + 13 )
#define STFL_HERC_SVS ( STFL_HERC_FIRST_BIT + 14 )
#define STFL_HERC_VIRTUAL_MACHINE ( STFL_HERC_FIRST_BIT + 15 )
+#define STFL_HERC_TCPIP_EXTENSION ( STFL_HERC_FIRST_BIT + 16 )
+#define STFL_HERC_TCPIP_PROB_STATE ( STFL_HERC_FIRST_BIT + 17 )
-#define STFL_HERC_LAST_BIT ( STFL_HERC_FIRST_BIT + 15 )
+#define STFL_HERC_LAST_BIT ( STFL_HERC_FIRST_BIT + 17 )
#define STFL_HERC_BY_SIZE (ROUND_UP( STFL_HERC_LAST_BIT, 8 ) / 8)
#define STFL_HERC_DW_SIZE (ROUND_UP( STFL_HERC_BY_SIZE, sizeof( DW )) / sizeof( DW ))
diff --git a/tcpip.c b/tcpip.c
new file mode 100644
index 000000000..dfec5738a
--- /dev/null
+++ b/tcpip.c
@@ -0,0 +1,1038 @@
+/*-------------------------------------------------------------------*/
+/* TCPIP.C (C) Copyright Jason Paul Winter, 2003,2010 */
+/* Minor adaptions for SDL Hyperion, Juergen Winkelmann 2019 */
+/* */
+/* C Socket Interface for the Hercules System/370, ESA/390, */
+/* ------------------ and z/Architecture Emulator */
+/* */
+/* This program was written by Jason Paul Winter. */
+/* */
+/* Copyright (c) 2003-2010, Jason Paul Winter */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with */
+/* or without modification, are permitted provided that */
+/* the following conditions are met: */
+/* */
+/* Redistributions of source code must retain the above */
+/* copyright notice, this list of conditions and the */
+/* following disclaimer. */
+/* */
+/* Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials */
+/* provided with the distribution. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR */
+/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
+/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR */
+/* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */
+/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
+/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
+/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
+/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH */
+/* DAMAGE. */
+/* */
+/*-------------------------------------------------------------------*/
+/* This module implements the backend to the TCPIP instruction by */
+/* mapping calls from the guest's socket library (EZASOKET or */
+/* equivalent) to native socket calls on the host. */
+/*-------------------------------------------------------------------*/
+
+#include "hstdinc.h"
+
+#define _TCPIP_C_
+#define _HENGINE_DLL_
+
+#include "hercules.h"
+#include "opcode.h"
+#include "inline.h"
+
+#include "tcpip.h"
+
+static u_int find_slot ( ULONG_PTR address ) {
+ u_int i;
+ i = 0;
+ obtain_lock (&tcpip_lock);
+ while ((((signed) map32[i]) != -1) && (i < Ccom-1)) i++;
+ map32[i] = address;
+ release_lock (&tcpip_lock);
+ return (i);
+}
+
+static void tcpip_init () {
+ u_int i;
+
+ initialize_lock(&tcpip_lock);
+
+ CerrGen = 0;
+
+ i = 0;
+ while (i < Ccom) {
+ map32[i] = -1;
+
+ Cselect [i] = NULL;
+
+ Cerr [i] = 0;
+ Ccom_blk [i] = 1;
+ Ccom_han [i] = -1;
+ Ccom_opn [i++] = 0;
+ }
+}
+
+/* This is the error translation routine for whatever host to Hercules: */
+static int Get_errno () {
+ u_int i;
+
+#ifndef _MSVC_
+ i = errno;
+#else
+ i = WSAGetLastError ();
+#endif
+
+ switch (i) {
+ case fEMFILE:
+ return (hEMFILE);
+/* case EAGAIN:
+ return (hEAGAIN); SAME AS EWOULDBLOCK*/
+ case EWOULDBLOCK:
+ return (hEWOULDBLOCK);
+ case EINPROGRESS:
+ return (hEINPROGRESS);
+ case EALREADY:
+ return (hEALREADY);
+ case ENOTSOCK:
+ return (hENOTSOCK);
+ case EDESTADDRREQ:
+ return (hEDESTADDRREQ);
+ case EMSGSIZE:
+ return (hEMSGSIZE);
+ case EPROTOTYPE:
+ return (hEPROTOTYPE);
+ case ENOPROTOOPT:
+ return (hENOPROTOOPT);
+ case EPROTONOSUPPORT:
+ return (hEPROTONOSUPPORT);
+ case ESOCKTNOSUPPORT:
+ return (hESOCKTNOSUPPORT);
+ case EOPNOTSUPP:
+ return (hEOPNOTSUPP);
+ case EPFNOSUPPORT:
+ return (hEPFNOSUPPORT);
+ case EAFNOSUPPORT:
+ return (hEAFNOSUPPORT);
+ case EADDRINUSE:
+ return (hEADDRINUSE);
+ case EADDRNOTAVAIL:
+ return (hEADDRNOTAVAIL);
+ case ENETDOWN:
+ return (hENETDOWN);
+ case ENETUNREACH:
+ return (hENETUNREACH);
+ case ENETRESET:
+ return (hENETRESET);
+ case ECONNABORTED:
+ return (hECONNABORTED);
+ case ECONNRESET:
+ return (hECONNRESET);
+ case ENOBUFS:
+ return (hENOBUFS);
+ case EISCONN:
+ return (hEISCONN);
+ case ENOTCONN:
+ return (hENOTCONN);
+ case ESHUTDOWN:
+ return (hESHUTDOWN);
+ case ETOOMANYREFS:
+ return (hETOOMANYREFS);
+ case ETIMEDOUT:
+ return (hETIMEDOUT);
+ case ECONNREFUSED:
+ return (hECONNREFUSED);
+ case fEINVAL :
+ return (hEINVAL);
+ case ELOOP :
+ return (hELOOP);
+ case fENAMETOOLONG :
+ return (hENAMETOOLONG);
+ case EHOSTDOWN :
+ return (hEHOSTDOWN);
+ case EHOSTUNREACH :
+ return (hEHOSTUNREACH);
+ case fENOTEMPTY :
+ return (hENOTEMPTY);
+#ifdef EPROCLIM // Some *nixs don't have this error
+ case EPROCLIM :
+ return (hEPROCLIM);
+#endif
+ case EUSERS :
+ return (hEUSERS);
+ case EDQUOT :
+ return (hEDQUOT);
+ case ESTALE :
+ return (hESTALE);
+ case EREMOTE :
+ return (hEREMOTE);
+ }
+
+ return (i);
+}
+
+/**********************************************************************************/
+
+#if defined(WORDS_BIGENDIAN)
+
+/*
+ regs comming in: (Non Intel Format - msb first.)
+ /--R0--\ /--R1--\
+ 00000000 xxxxxxxx 00000000 yyyyyyyy ...
+ (Zeros are the 64bit register parts, never used in S370.)
+*/
+
+static void set_reg (u_int * regs, u_int r, u_int v) {
+ regs [(r * 2) + 1] = v;
+}
+
+static u_int get_reg (u_int * regs, u_int r) {
+ return (regs [(r * 2) + 1]);
+}
+
+#else
+
+/*
+ regs comming in: (Intel Format - lsb first.)
+ /--R0--\ /--R1--\
+ xxxxxxxx 00000000 yyyyyyyy 00000000 ...
+ (Zeros are the 64bit register parts, never used in S370.)
+*/
+
+static void set_reg (u_int * regs, u_int r, u_int v) {
+ regs [r * 2] = v;
+}
+
+static u_int get_reg (u_int * regs, u_int r) {
+ return (regs [r * 2]);
+}
+
+#endif
+
+/**********************************************************************************/
+
+static u_int check_not_sock (u_int s, talk_ptr t) {
+
+ if ((s < 1) || (s >= Ccom)) {
+ t->ret_cd = -1;
+ return (1);
+ }
+
+ if (Ccom_han [s] == -1) {
+ t->ret_cd = -1;
+ return (1);
+ }
+
+ return (0);
+}
+
+static void EZASOKET (u_int func, int aux1, int aux2, talk_ptr t) {
+ int i;
+ socklen_t isock;
+ int k;
+ int l;
+ int m;
+ int size;
+ struct hostent * hp;
+ struct timeval timeout;
+ fd_set sockets;
+ SOCKADDR_IN Clocal_adx;
+ SOCKADDR Slocal_adx;
+
+ switch (func & 0xFF) {
+ case 1: /* INITAPI */
+
+ t->ret_cd = 0;
+ return;
+
+ case 2: /* GETERRORS */
+
+ if (check_not_sock (aux1, t)) {
+ t->ret_cd = hENOTSOCK;
+ return;
+ }
+
+ t->ret_cd = Cerr [aux1];
+ return;
+
+ case 3: /* GETERROR */
+
+ t->ret_cd = CerrGen;
+ return;
+
+ case 4: /* GETHOSTBYNAME */
+
+ m = strlen (t->buffer_in);
+ k = 0;
+ while (m) {
+ t->buffer_in [k] = DCCebcdic_to_ascii [(unsigned char)(t->buffer_in [k])];
+ if ((unsigned char)t->buffer_in [k] == 0x20) {t->buffer_in [k] = 0; break;};
+ k++;
+ m--;
+ }
+
+ if ((hp = gethostbyname (t->buffer_in)) == NULL) {
+
+ CerrGen = Get_errno ();
+
+ t->ret_cd = 0;
+ return;
+ } else {
+ if (hp->h_addr_list [0] == NULL) {
+ t->ret_cd = 0;
+ return;
+ } else {
+ t->ret_cd = (ntohl(((u_int *)(hp->h_addr_list [0])) [0]));
+ return;
+ }
+ }
+
+ case 5: /* SOCKET */
+
+ obtain_lock (&tcpip_lock);
+
+ m = 1;
+ while (m < Ccom) {
+ if (Ccom_opn [m] == 0) break;
+ m++;
+ }
+ if (m == Ccom) {
+
+ CerrGen = hEMFILE;
+
+ release_lock (&tcpip_lock);
+
+ t->ret_cd = -1;
+ return; /* None available. */
+ }
+
+ i = aux1 >> 16; /* Family: eg. PF_INET */
+
+ if ((Ccom_han [m] = socket (i, (aux1 & 0xFFFF), aux2)) == INVALID_SOCKET) {
+
+ CerrGen = Get_errno ();
+
+ release_lock (&tcpip_lock);
+
+ t->ret_cd = -1;
+ return; /* ERROR */
+ }
+
+ Ccom_opn [m] = 1;
+
+ release_lock (&tcpip_lock);
+
+ t->ret_cd = m;
+ return;
+
+ case 6: /* BIND */
+
+ /* FUNC:SOCK&FUNC, AUX1:ADDRESS, AUX2:FAMILY&PORT */
+
+ m = func >> 16; /* SOCKET # */
+ i = aux2 >> 16; /* Family */
+
+ if (check_not_sock (m, t)) return;
+
+#if defined(__APPLE__)
+ bzero ((LPSOCKADDR)&Clocal_adx, sizeof (Clocal_adx)); /* cleanup address */
+#endif
+
+ /* set up socket */
+ Clocal_adx.sin_family = (short)(i & 0xFF);
+
+ Clocal_adx.sin_addr.s_addr = htonl (aux1);
+
+ Clocal_adx.sin_port = htons ((unsigned short)(aux2 & 0xFFFF));
+
+ if (bind (Ccom_han [m], (LPSOCKADDR)&Clocal_adx, sizeof (Clocal_adx))) {
+
+ Cerr [m] = Get_errno ();
+
+ t->ret_cd = -1;
+ return; /* ERROR */
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 7: /* CONNECT */
+
+ m = func >> 16; /* SOCKET # */
+ i = aux2 >> 16; /* Family */
+
+ if (check_not_sock (m, t)) return;
+
+ /* set up socket */
+ Clocal_adx.sin_family = (short)(i & 0xFF);
+
+ Clocal_adx.sin_addr.s_addr = htonl (aux1);
+
+ Clocal_adx.sin_port = htons ((unsigned short)(aux2 & 0xFFFF));
+
+ k = 1;
+ ioctlsocket (Ccom_han [m], FIONBIO, &k);
+
+ i = connect (Ccom_han [m], (LPSOCKADDR)&Clocal_adx, sizeof (Clocal_adx));
+ Cerr [m] = Get_errno ();
+
+ k = 0;
+ ioctlsocket (Ccom_han [m], FIONBIO, &k);
+
+ if (i == -1) {
+
+ switch (Cerr [m]) {
+ case hEISCONN :
+ t->ret_cd = 0; /* Worked! */
+ return;
+
+ case hEINVAL : /* WSAEALREADY in Windows old sockets */
+ case hEALREADY :
+ case hEWOULDBLOCK :
+ case hEINPROGRESS :
+
+ if (Ccom_blk [m] == 0) {
+ t->ret_cd = -1;
+ return; /* ERROR, But Client Knows... */
+ }
+
+ t->ret_cd = -2; /* Must wait. */
+ return;
+ }
+
+ t->ret_cd = -1;
+ return; /* ERROR */
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 8: /* LISTEN */
+
+ if (check_not_sock (aux1, t)) return;
+
+ i = aux2;
+ if (i == 0) i = SOMAXCONN;
+
+ if (listen (Ccom_han [aux1], i)) {
+
+ Cerr [aux1] = Get_errno ();
+
+ t->ret_cd = -1;
+ return; /* ERROR */
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 9: /* ACCEPT */
+
+ if (check_not_sock (aux1, t)) return;
+
+ obtain_lock (&tcpip_lock);
+
+ m = 1;
+ while (m < Ccom) {
+ if (Ccom_opn [m] == 0) break;
+ m++;
+ }
+
+ if (m == Ccom) {
+
+ Cerr [aux1] = hEMFILE;
+
+ release_lock (&tcpip_lock);
+
+ t->ret_cd = -1;
+ return; /* None available. */
+ }
+
+ isock = sizeof (Slocal_adx);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ FD_ZERO (&sockets);
+ FD_SET (Ccom_han [aux1], &sockets);
+
+ if (select (Ccom_han [aux1] + 1, &sockets, NULL, NULL, &timeout) == 0) {
+
+ release_lock (&tcpip_lock);
+
+ if (Ccom_blk [aux1]) {
+ t->ret_cd = -2;
+ } else {
+ Cerr [aux1] = hEWOULDBLOCK;
+ t->ret_cd = -1;
+ }
+ return;
+ }
+
+ l = Ccom_han [m] = accept (Ccom_han [aux1], &Slocal_adx, &isock);
+
+ if (l == INVALID_SOCKET) {
+
+ Cerr [aux1] = Get_errno ();
+
+ release_lock (&tcpip_lock);
+
+ t->ret_cd = -1;
+ return; /* ERROR */
+ }
+
+ Ccom_opn [m] = 1;
+
+ release_lock (&tcpip_lock);
+
+ t->len_out = sizeof (Clocal_adx);
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+ memcpy (t->buffer_out, &Slocal_adx, t->len_out);
+ ((SOCKADDR_IN *)(t->buffer_out))->sin_family = htons (((SOCKADDR_IN *)(t->buffer_out))->sin_family);
+
+ t->ret_cd = m;
+ return;
+
+ case 10: /* SEND */
+
+ if (check_not_sock (aux1, t)) return;
+
+ if ((l = send (Ccom_han [aux1], t->buffer_in, t->len_in, 0)) == SOCKET_ERROR) {
+
+ Cerr [aux1] = Get_errno ();
+
+ t->ret_cd = -1;
+ return;
+ }
+
+ t->ret_cd = l;
+ return;
+
+ case 11: /* RECV */
+
+ if (check_not_sock (aux1, t)) return;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ FD_ZERO (&sockets);
+ FD_SET (Ccom_han [aux1], &sockets);
+
+ if (select (Ccom_han [aux1] + 1, &sockets, NULL, NULL, &timeout) == 0) {
+
+ if (Ccom_blk [aux1]) {
+ t->ret_cd = -2;
+ } else {
+ Cerr [aux1] = hEWOULDBLOCK;
+ t->ret_cd = -1;
+ }
+ return;
+ }
+
+ t->buffer_out = (char *)malloc (aux2);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+
+ if ((size = recv (Ccom_han [aux1], t->buffer_out, aux2, 0)) == SOCKET_ERROR) { /* receive command */
+
+ Cerr [aux1] = Get_errno ();
+
+ t->len_out = 0;
+ map32[t->buffer_out_slot] = -1;
+ free (t->buffer_out);
+ t->buffer_out = NULL;
+
+ t->ret_cd = -1;
+ return;
+ }
+
+ t->len_out = size;
+ t->ret_cd = size;
+ return;
+
+ case 12: /* CLOSE */
+
+ if ((aux1 > 0) && (aux1 < Ccom)) {
+ /* close connection */
+ if (Ccom_opn [aux1])
+ closesocket (Ccom_han [aux1]);
+
+ Ccom_opn [aux1] = 0;
+ Ccom_han [aux1] = -1;
+ Ccom_blk [aux1] = 1;
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 13: /* EBCDIC2ASCII */
+
+ t->len_out = t->len_in;
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+
+ m = t->len_out;
+ i = 0;
+ k = 0;
+ while (m) {
+ t->buffer_out [k++] = DCCebcdic_to_ascii [(unsigned char)(t->buffer_in [i++])];
+ m--;
+ }
+
+ t->ret_cd = t->len_out;
+ return;
+
+ case 14: /* ASCII2EBCDIC */
+
+ t->len_out = t->len_in;
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+
+ m = t->len_out;
+ i = 0;
+ k = 0;
+ while (m) {
+ t->buffer_out [k++] = DCCascii_to_ebcdic [(unsigned char)(t->buffer_in [i++])];
+ m--;
+ }
+
+ t->ret_cd = t->len_out;
+ return;
+
+ case 15: /* IOCTL */
+
+ m = func >> 16;
+
+ if (check_not_sock (m, t)) return;
+
+ if (aux1 == 1) {
+
+ if (aux2) {
+ Ccom_blk [m] = 0; /* No longer blocking */
+ } else {
+ Ccom_blk [m] = 1;
+ }
+
+ t->ret_cd = 0;
+
+ } else {
+
+ i = ioctlsocket (Ccom_han [m], FIONREAD, &(t->ret_cd));
+ if (i == -1) {
+ t->ret_cd = -1;
+ Cerr [m] = Get_errno ();
+ }
+ }
+
+ return;
+
+ case 16: /* GETSOCKNAME */
+
+ if (check_not_sock (aux1, t)) return;
+
+ t->len_out = sizeof (Clocal_adx);
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+
+ isock = t->len_out;
+ t->ret_cd = getsockname (Ccom_han [aux1], (struct sockaddr *)(t->buffer_out), &isock);
+
+ if (t->ret_cd == -1) {
+ Cerr [aux1] = Get_errno ();
+ } else {
+ ((SOCKADDR_IN *)(t->buffer_out))->sin_family = htons (((SOCKADDR_IN *)(t->buffer_out))->sin_family);
+ }
+
+ return;
+
+ case 17: /* SELECT */
+
+ /* func>>16 = socket
+ aux1 = func subcode
+ aux2 = maxsock+1 */
+
+ m = func >> 16;
+
+ if (check_not_sock (m, t)) return;
+
+ switch (aux1 & 0xFF) {
+ case 0: /* Start */
+ if (Cselect [m] == NULL) { /* Start-part */
+
+ Cselect [m] = malloc (sizeof (selects));
+
+ Cselect [m]->ri = malloc (sizeof (fd_set));
+ Cselect [m]->wi = malloc (sizeof (fd_set));
+ Cselect [m]->ei = malloc (sizeof (fd_set));
+
+ Cselect [m]->ro = malloc (sizeof (fd_set));
+ Cselect [m]->wo = malloc (sizeof (fd_set));
+ Cselect [m]->eo = malloc (sizeof (fd_set));
+ }
+
+ FD_ZERO ((fd_set *)(Cselect [m]->ri));
+ FD_ZERO ((fd_set *)(Cselect [m]->wi));
+ FD_ZERO ((fd_set *)(Cselect [m]->ei));
+
+ Cselect [m]->len = 0;
+ Cselect [m]->invalid = 0;
+
+ t->ret_cd = 0;
+ return;
+
+ case 1: /* Read Inputs */
+
+ Cselect [m]->len = t->len_in; /* Copy every time... */
+
+ /* Need to bswap every long in the incoming array... */
+ i = t->len_in / 4;
+ while (i) {
+ i--;
+ ((u_int *)t->buffer_in) [i] = htonl (((u_int *)t->buffer_in) [i]);
+ }
+
+ i = 0;
+ while (i < aux2) {
+ if (hercFD_ISSET (i, (hercfd_set *)(t->buffer_in))) {
+ if (Ccom_han [i] == -1) {
+ Cselect [m]->invalid = 1;
+ } else {
+ FD_SET (Ccom_han [i], (fd_set *)(Cselect [m]->ri));
+ }
+ }
+ i++;
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 2: /* Write Inputs */
+
+ Cselect [m]->len = t->len_in; /* Copy every time... */
+
+ /* Need to bswap every long in the incoming array... */
+ i = t->len_in / 4;
+ while (i) {
+ i--;
+ ((u_int *)t->buffer_in) [i] = htonl (((u_int *)t->buffer_in) [i]);
+ }
+
+ i = 0;
+ while (i < aux2) {
+ if (hercFD_ISSET (i, (hercfd_set *)(t->buffer_in))) {
+ if (Ccom_han [i] == -1) {
+ Cselect [m]->invalid = 1;
+ } else {
+ FD_SET (Ccom_han [i], (fd_set *)(Cselect [m]->wi));
+ }
+ }
+ i++;
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 3: /* Exception Inputs */
+
+ Cselect [m]->len = t->len_in; /* Copy every time... */
+
+ /* Need to bswap every long in the incoming array... */
+ i = t->len_in / 4;
+ while (i) {
+ i--;
+ ((u_int *)t->buffer_in) [i] = htonl (((u_int *)t->buffer_in) [i]);
+ }
+
+ i = 0;
+ while (i < aux2) {
+ if (hercFD_ISSET (i, (hercfd_set *)(t->buffer_in))) {
+ if (Ccom_han [i] == -1) {
+ Cselect [m]->invalid = 1;
+ } else {
+ FD_SET (Ccom_han [i], (fd_set *)(Cselect [m]->ei));
+ }
+ }
+ i++;
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 4: /* Run 'select' (never blocking here, so may loop back.) */
+
+ memcpy (Cselect [m]->ro, Cselect [m]->ri, sizeof (fd_set));
+ memcpy (Cselect [m]->wo, Cselect [m]->wi, sizeof (fd_set));
+ memcpy (Cselect [m]->eo, Cselect [m]->ei, sizeof (fd_set));
+
+ if (Cselect [m]->invalid) {
+ Cerr [m] = hENOTSOCK;
+ t->ret_cd = -1;
+ return;
+ }
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ i = select (Ccom_han [aux2 - 1] + 1,
+ (fd_set *)(Cselect [m]->ro),
+ (fd_set *)(Cselect [m]->wo),
+ (fd_set *)(Cselect [m]->eo),
+ &timeout);
+
+ if (i == 0) {
+ t->ret_cd = -2; /* Let the caller decide what to do. */
+ } else {
+ t->ret_cd = i;
+ }
+ return;
+
+ case 5: /* Read Outputs */
+
+ t->len_out = Cselect [m]->len;
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+ memset (t->buffer_out, 0, t->len_out);
+
+ i = 0;
+ while (i < aux2) {
+ if (Ccom_han [i] != -1)
+ if (FD_ISSET (Ccom_han [i], (fd_set *)(Cselect [m]->ro)))
+ hercFD_SET (i, (hercfd_set *)(t->buffer_out));
+ i++;
+ }
+
+ /* Need to bswap every long in the outgoing array... */
+ i = t->len_out / 4;
+ while (i) {
+ i--;
+ ((u_int *)t->buffer_out) [i] = htonl (((u_int *)t->buffer_out) [i]);
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 6: /* Write Outputs */
+
+ t->len_out = Cselect [m]->len;
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+ memset (t->buffer_out, 0, t->len_out);
+
+ i = 0;
+ while (i < aux2) {
+ if (Ccom_han [i] != -1)
+ if (FD_ISSET (Ccom_han [i], (fd_set *)(Cselect [m]->wo)))
+ hercFD_SET (i, (hercfd_set *)(t->buffer_out));
+ i++;
+ }
+
+ /* Need to bswap every long in the outgoing array... */
+ i = t->len_out / 4;
+ while (i) {
+ i--;
+ ((u_int *)t->buffer_out) [i] = htonl (((u_int *)t->buffer_out) [i]);
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 7: /* Exception Outputs */
+
+ t->len_out = Cselect [m]->len;
+ t->buffer_out = (char *)malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+ memset (t->buffer_out, 0, t->len_out);
+
+ i = 0;
+ while (i < aux2) {
+ if (Ccom_han [i] != -1)
+ if (FD_ISSET (Ccom_han [i], (fd_set *)(Cselect [m]->eo)))
+ hercFD_SET (i, (hercfd_set *)(t->buffer_out));
+ i++;
+ }
+
+ /* Need to bswap every long in the outgoing array... */
+ i = t->len_out / 4;
+ while (i) {
+ i--;
+ ((u_int *)t->buffer_out) [i] = htonl (((u_int *)t->buffer_out) [i]);
+ }
+
+ t->ret_cd = 0;
+ return;
+
+ case 8: /* Finish */
+
+ if (Cselect [m] != NULL) { /* Clean-up */
+
+ free (Cselect [m]->ri);
+ free (Cselect [m]->wi);
+ free (Cselect [m]->ei);
+
+ free (Cselect [m]->ro);
+ free (Cselect [m]->wo);
+ free (Cselect [m]->eo);
+
+ free (Cselect [m]);
+ Cselect [m] = NULL;
+ }
+
+ t->ret_cd = 0;
+ return;
+ }
+
+ return;
+
+ case 18: /* GETHOSTBYADDR */
+
+ isock = sizeof (Slocal_adx);
+ i = htonl (aux1);
+
+#ifdef _MSVC_
+ if ((hp = gethostbyaddr ((const char *) &i, isock, AF_INET)) == NULL) {
+#else
+ if ((hp = gethostbyaddr (&i, isock, AF_INET)) == NULL) {
+#endif
+
+ CerrGen = Get_errno ();
+
+ t->ret_cd = 0;
+ return;
+ } else {
+ if (!(t->ret_cd = strlen (hp->h_name) )) {
+ t->ret_cd = 0;
+ return;
+ } else {
+
+ t->len_out = t->ret_cd;
+ t->buffer_out = (char *) malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+
+ m = t->ret_cd;
+ i = 0;
+ k = 0;
+ while (m) {
+ t->buffer_out [k++] = DCCascii_to_ebcdic [(unsigned char)(hp->h_name [i++])];
+ m--;
+ }
+ return;
+ }
+ }
+
+ case 19: /* GETPEERNAME */
+
+ if (check_not_sock (aux1, t)) return;
+
+ t->len_out = sizeof (Clocal_adx);
+ t->buffer_out = (char *) malloc (t->len_out);
+ t->buffer_out_slot = find_slot ((ULONG_PTR)&(t->buffer_out [0]));
+
+ isock = t->len_out;
+ t->ret_cd = getpeername (Ccom_han [aux1], (struct sockaddr *)(t->buffer_out), &isock);
+
+ if (t->ret_cd == -1) {
+ Cerr [aux1] = Get_errno ();
+ } else {
+ ((SOCKADDR_IN *)(t->buffer_out))->sin_family = htons (((SOCKADDR_IN *)(t->buffer_out))->sin_family);
+ }
+
+ return;
+
+ }
+
+ t->ret_cd = 0;
+ return;
+}
+
+/**********************************************************************************/
+/*
+ R0 = 0 (Initially, but turns to > 0 after the native call.
+ R1 = Byte Counter
+ R2 = Source/Destination of PC buffer. 32bits.
+ R3 = Direction (0 = to Host PC, 1 = from Host PC)
+ R4 = Returned Bytes
+
+ R7 = Function
+ R8 = Aux. value 1
+ R9 = Aux. value 2
+
+ R14 = Identifier (returned & passed back for conversations.)
+ R15 = Work Variable / Return Code
+*/
+
+u_int lar_tcpip (u_int * regs) {
+ talk_ptr t;
+
+ if (tcpip_init_req) {
+ tcpip_init_req = 0;
+ tcpip_init ();
+ }
+
+ if (get_reg (regs, 0) == 0) { /* Initial call. */
+
+ if (get_reg (regs, 3) == 0) { /* Alloc memory for this communication. */
+
+ t = (talk_ptr)malloc (sizeof (talk));
+ t->slot = find_slot ((ULONG_PTR)t);
+
+ t->len_in = get_reg (regs, 1);
+ t->buffer_in = (char *)malloc (t->len_in + 1);
+ t->buffer_in_slot = find_slot ((ULONG_PTR)&(t->buffer_in [0]));
+ t->buffer_in [t->len_in] = 0; /* NULL Terminator */
+
+ t->len_out = 0;
+ t->buffer_out = NULL; /* I've got nothing, at the moment */
+ t->ret_cd = 0;
+
+ set_reg (regs, 14, (u_int )t->slot);
+
+ set_reg (regs, 2, (u_int )t->buffer_in_slot);
+
+ } else { /* They want some return info... */
+
+ t = (talk_ptr)map32[get_reg (regs, 14)];
+
+ set_reg (regs, 1, t->len_out);
+ set_reg (regs, 2, (u_int )t->buffer_out_slot);
+
+ set_reg (regs, 4, t->ret_cd);
+ }
+
+ } else { /* Must need additional processing. */
+
+ t = (talk_ptr)map32[get_reg (regs, 14)];
+
+ if (get_reg (regs, 3) == 0) { /* Run. */
+
+ EZASOKET (get_reg (regs, 7), get_reg (regs, 8), get_reg (regs, 9), t);
+
+ } else { /* Dealloc memory for this communication. */
+
+ map32[t->buffer_in_slot] = -1;
+ free (t->buffer_in);
+ if (t->buffer_out) {
+ map32[t->buffer_out_slot] = -1;
+ free (t->buffer_out);
+ }
+ map32[t->slot] = -1;
+ free (t);
+
+ set_reg (regs, 14, 0);
+ }
+ }
+
+ return (1); /* We never return 0, that's for the DLL Loader. */
+}
+
+/**********************************************************************************/
diff --git a/tcpip.h b/tcpip.h
new file mode 100644
index 000000000..a8c1b90c0
--- /dev/null
+++ b/tcpip.h
@@ -0,0 +1,288 @@
+/*-------------------------------------------------------------------*/
+/* TCPIP.H (C) Copyright Jason Paul Winter, 2003,2010 */
+/* Minor adaptions for SDL Hyperion, Juergen Winkelmann 2019 */
+/*-------------------------------------------------------------------*/
+
+#define Ccom 1024 /* maximum number of concurrent connections + 1 */
+
+#ifndef _MSVC_
+typedef unsigned long ULONG_PTR;
+#endif
+
+#if !defined( _X75_C_ )
+#ifndef _MSVC_
+
+/* Convert Windows declarations back to normal *nix types if needed: */
+
+#define SOCKET int
+#define SOCKADDR struct sockaddr
+#define SOCKADDR_IN struct sockaddr_in
+#define LPSOCKADDR struct sockaddr *
+
+#define closesocket close
+#define ioctlsocket ioctl
+
+#define INVALID_SOCKET -1
+#define SOCKET_ERROR -1
+
+#endif
+
+typedef struct talk_tag * talk_ptr;
+typedef struct talk_tag {
+ u_int len_in;
+ char * buffer_in;
+ u_int len_out;
+ char * buffer_out;
+ int ret_cd;
+ u_int slot;
+ u_int buffer_in_slot;
+ u_int buffer_out_slot;
+} talk;
+
+typedef struct selects_tag * selects_ptr;
+typedef struct selects_tag {
+ u_int len;
+ u_int invalid;
+ u_int * ri;
+ u_int * wi;
+ u_int * ei;
+ u_int * ro;
+ u_int * wo;
+ u_int * eo;
+} selects;
+
+
+#define hercNBBY 8
+#define hercFD_SETSIZE 256
+typedef u_int hercfd_mask;
+#define hercNFDBITS (sizeof(hercfd_mask) * hercNBBY)
+#define herchowmany(x, y) (((x) + ((y) - 1)) / (y))
+
+typedef struct hercfd_set {
+ hercfd_mask hercfds_bits [herchowmany(hercFD_SETSIZE, hercNFDBITS)];
+} hercfd_set;
+
+#define hercFD_SET(n, p) ((p)->hercfds_bits[(n)/hercNFDBITS] |= (1 << ((n) % hercNFDBITS)))
+#define hercFD_CLR(n, p) ((p)->hercfds_bits[(n)/hercNFDBITS] &= ~(1 << ((n) % hercNFDBITS)))
+#define hercFD_ISSET(n, p) ((p)->hercfds_bits[(n)/hercNFDBITS] & (1 << ((n) % hercNFDBITS)))
+
+#ifdef _MSVC_
+
+/* When using MSVC, just use the normal critical section functions: */
+
+#undef initialize_lock
+#undef LOCK
+#undef obtain_lock
+#undef release_lock
+
+#define initialize_lock InitializeCriticalSection
+#define LOCK CRITICAL_SECTION
+#define obtain_lock EnterCriticalSection
+#define release_lock LeaveCriticalSection
+
+#endif
+
+#define hEMFILE 24 /* Too many open files */
+/* non-blocking and interrupt i/o */
+#define hEAGAIN 35 /* Resource temporarily unavailable */
+#define hEWOULDBLOCK hEAGAIN /* Operation would block */
+#define hEINPROGRESS 36 /* Operation now in progress */
+#define hEALREADY 37 /* Operation already in progress */
+
+/* ipc/network software -- argument errors */
+#define hENOTSOCK 38 /* Socket operation on non-socket */
+#define hEDESTADDRREQ 39 /* Destination address required */
+#define hEMSGSIZE 40 /* Message too int */
+#define hEPROTOTYPE 41 /* Protocol wrong type for socket */
+#define hENOPROTOOPT 42 /* Protocol not available */
+#define hEPROTONOSUPPORT 43 /* Protocol not supported */
+#define hESOCKTNOSUPPORT 44 /* Socket type not supported */
+#define hEOPNOTSUPP 45 /* Operation not supported */
+#define hEPFNOSUPPORT 46 /* Protocol family not supported */
+#define hEAFNOSUPPORT 47 /* Address family not supported by protocol family */
+#define hEADDRINUSE 48 /* Address already in use */
+#define hEADDRNOTAVAIL 49 /* Can't assign requested address */
+
+/* ipc/network software -- operational errors */
+#define hENETDOWN 50 /* Network is down */
+#define hENETUNREACH 51 /* Network is unreachable */
+#define hENETRESET 52 /* Network dropped connection on reset */
+#define hECONNABORTED 53 /* Software caused connection abort */
+#define hECONNRESET 54 /* Connection reset by peer */
+#define hENOBUFS 55 /* No buffer space available */
+#define hEISCONN 56 /* Socket is already connected */
+#define hENOTCONN 57 /* Socket is not connected */
+#define hESHUTDOWN 58 /* Can't send after socket shutdown */
+#define hETOOMANYREFS 59 /* Too many references: can't splice */
+#define hETIMEDOUT 60 /* Operation timed out */
+#define hECONNREFUSED 61 /* Connection refused */
+
+/* Other */
+#define hEINVAL 22 /* Invalid argument */
+#define hELOOP 62 /* Too many levels of symbolic links */
+#define hENAMETOOLONG 63 /* File name too int */
+#define hEHOSTDOWN 64 /* Host is down */
+#define hEHOSTUNREACH 65 /* No route to host */
+#define hENOTEMPTY 66 /* Directory not empty */
+#define hEPROCLIM 67 /* Too many processes */
+#define hEUSERS 68 /* Too many users */
+#define hEDQUOT 69 /* Disc quota exceeded */
+#define hESTALE 70 /* Stale NFS file handle */
+#define hEREMOTE 71 /* Too many levels of remote in path */
+
+#ifndef _MSVC_
+
+/* Reverse my MSVC changes for Non MSVC compilers: */
+
+#define fEMFILE EMFILE
+#define fEINVAL EINVAL
+#define fENAMETOOLONG ENAMETOOLONG
+#define fENOTEMPTY ENOTEMPTY
+
+#else
+
+/* New MSVC compilers have EMFILE, EINVAL, ENAMETOOLONG and ENOTEMPTY */
+/* defined in multiple places - so some new code here adds a 'f'ix! */
+/* This is what we need to do with error #s: Windows->Unix->Hercules */
+
+#undef fEMFILE
+#undef EWOULDBLOCK
+#undef EINPROGRESS
+#undef EALREADY
+
+#undef ENOTSOCK
+#undef EDESTADDRREQ
+#undef EMSGSIZE
+#undef EPROTOTYPE
+#undef ENOPROTOOPT
+#undef EPROTONOSUPPORT
+#undef ESOCKTNOSUPPORT
+#undef EOPNOTSUPP
+#undef EPFNOSUPPORT
+#undef EAFNOSUPPORT
+#undef EADDRINUSE
+#undef EADDRNOTAVAIL
+
+#undef ENETDOWN
+#undef ENETUNREACH
+#undef ENETRESET
+#undef ECONNABORTED
+#undef ECONNRESET
+#undef ENOBUFS
+#undef EISCONN
+#undef ENOTCONN
+#undef ESHUTDOWN
+#undef ETOOMANYREFS
+#undef ETIMEDOUT
+#undef ECONNREFUSED
+
+#undef fEINVAL
+#undef ELOOP
+#undef fENAMETOOLONG
+#undef EHOSTDOWN
+#undef EHOSTUNREACH
+#undef fENOTEMPTY
+#undef EPROCLIM
+#undef EUSERS
+#undef EDQUOT
+#undef ESTALE
+#undef EREMOTE
+
+#define fEMFILE WSAEMFILE
+#define EWOULDBLOCK WSAEWOULDBLOCK /* Is also EAGAIN */
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+
+#define fEINVAL WSAEINVAL
+#define ELOOP WSAELOOP
+#define fENAMETOOLONG WSAENAMETOOLONG
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#define fENOTEMPTY WSAENOTEMPTY
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+
+#endif
+
+static unsigned char DCCascii_to_ebcdic[] = {
+ "\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x15\x0B\x0C\x0D\x0E\x0F"
+ "\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x3F\x27\x1C\x1D\x1E\x1F"
+ "\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61"
+ "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F"
+ "\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6"
+ "\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D"
+ "\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96"
+ "\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x4F\xD0\xA1\x07"
+ "\x20\x21\x22\x23\x24\x25\x06\x17\x28\x29\x2A\x2B\x2C\x09\x0A\x1B"
+ "\x30\x31\x1A\x33\x34\x35\x36\x08\x38\x39\x3A\x3B\x04\x14\x3E\xFF"
+ "\x41\xAA\x4A\xB1\x9F\xB2\x6A\xB5\xBB\xB4\x9A\x8A\xB0\xCA\xAF\xBC"
+ "\x90\x8F\xEA\xFA\xBE\xA0\xB6\xB3\x9D\xDA\x9B\x8B\xB7\xB8\xB9\xAB"
+ "\x64\x65\x62\x66\x63\x67\x9E\x68\x74\x71\x72\x73\x78\x75\x76\x77"
+ "\xAC\x69\xED\xEE\xEB\xEF\xEC\xBF\x80\xFD\xFE\xFB\xFC\xBA\xAE\x59"
+ "\x44\x45\x42\x46\x43\x47\x9C\x48\x54\x51\x52\x53\x58\x55\x56\x57"
+ "\x8C\x49\xCD\xCE\xCB\xCF\xCC\xE1\x70\xDD\xDE\xDB\xDC\x8D\x8E\xDF"
+};
+
+static unsigned char DCCebcdic_to_ascii[] = {
+ "\x00\x01\x02\x03\x9C\x09\x86\x7F\x97\x8D\x8E\x0B\x0C\x0D\x0E\x0F"
+ "\x10\x11\x12\x13\x9D\x0A\x08\x87\x18\x19\x92\x8F\x1C\x1D\x1E\x1F"
+ "\x80\x81\x82\x83\x84\x85\x17\x1B\x88\x89\x8A\x8B\x8C\x05\x06\x07"
+ "\x90\x91\x16\x93\x94\x95\x96\x04\x98\x99\x9A\x9B\x14\x15\x9E\x1A"
+ "\x20\xA0\xE2\xE4\xE0\xE1\xE3\xE5\xE7\xF1\xA2\x2E\x3C\x28\x2B\x7C"
+ "\x26\xE9\xEA\xEB\xE8\xED\xEE\xEF\xEC\xDF\x21\x24\x2A\x29\x3B\x5E"
+ "\x2D\x2F\xC2\xC4\xC0\xC1\xC3\xC5\xC7\xD1\xA6\x2C\x25\x5F\x3E\x3F"
+ "\xF8\xC9\xCA\xCB\xC8\xCD\xCE\xCF\xCC\x60\x3A\x23\x40\x27\x3D\x22"
+ "\xD8\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAB\xBB\xF0\xFD\xFE\xB1"
+ "\xB0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xAA\xBA\xE6\xB8\xC6\xA4"
+ "\xB5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xA1\xBF\xD0\x5B\xDE\xAE"
+ "\xAC\xA3\xA5\xB7\xA9\xA7\xB6\xBC\xBD\xBE\xDD\xA8\xAF\x5D\xB4\xD7"
+ "\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xAD\xF4\xF6\xF2\xF3\xF5"
+ "\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xB9\xFB\xFC\xF9\xFA\xFF"
+ "\x5C\xF7\x53\x54\x55\x56\x57\x58\x59\x5A\xB2\xD4\xD6\xD2\xD3\xD5"
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xB3\xDB\xDC\xD9\xDA\x9F"
+};
+
+static char Ccom_opn [Ccom];
+static char Ccom_blk [Ccom]; /* Is a blocking socket? */
+static SOCKET Ccom_han [Ccom];
+
+static u_int CerrGen; /* Last error, thread-dodgy but it's only used for "non socket" errors */
+static u_int Cerr [Ccom]; /* Last error for specific socket, this one is thread safe. */
+
+static selects_ptr Cselect [Ccom]; /* Array for the 3 arrays of select input/output data */
+
+static LOCK tcpip_lock;
+
+static u_int tcpip_init_req = 1;
+
+ULONG_PTR map32[Ccom];
+#endif /*!defined( _X75_C_ )*/
diff --git a/x75.c b/x75.c
new file mode 100644
index 000000000..152966c67
--- /dev/null
+++ b/x75.c
@@ -0,0 +1,140 @@
+/*-------------------------------------------------------------------*/
+/* X75.C (C) Copyright Jason Paul Winter, 2003,2010 */
+/* Minor adaptions for SDL Hyperion, Juergen Winkelmann 2019 */
+/* */
+/* This program was written by Jason Paul Winter. It was originally */
+/* named DYN75.C. */
+/* */
+/* Copyright (c) 2003-2010, Jason Paul Winter */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with */
+/* or without modification, are permitted provided that */
+/* the following conditions are met: */
+/* */
+/* Redistributions of source code must retain the above */
+/* copyright notice, this list of conditions and the */
+/* following disclaimer. */
+/* */
+/* Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials */
+/* provided with the distribution. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR */
+/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
+/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR */
+/* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */
+/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
+/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
+/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
+/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH */
+/* DAMAGE. */
+/* */
+/*-------------------------------------------------------------------*/
+/* This module implements the TCPIP instruction, which allows guest */
+/* access to the host's TCP/IP stack. Register usage is as follows: */
+/* */
+/* R0 = 0 (Initially, but turns to > 0 after the native call. */
+/* R1 = Byte Counter */
+/* R2 = Source/Destination of PC buffer. 32bits. */
+/* R3 = Direction (0 = to Host PC, 1 = from Host PC) */
+/* R4 = Returned Bytes */
+/* */
+/* R7 \ */
+/* R8 |= Used by the lar_tcpip function (but not here.) */
+/* R9 / */
+/* */
+/* R14 = Identifier (returned & passed back for conversations.) */
+/* R15 = Work Variable / Return Code */
+/*-------------------------------------------------------------------*/
+
+#include "hstdinc.h"
+
+#define _X75_C_
+#define _HENGINE_DLL_
+
+#include "hercules.h"
+#include "opcode.h"
+#include "inline.h"
+
+#include "tcpip.h"
+#include "x75.h"
+
+#if defined( FEATURE_TCPIP_EXTENSION )
+/*-------------------------------------------------------------------*/
+/* 75xx TCPIP Ra,yyy(Rb,Rc) Ra=anything, Rc>4<14, Rb=0/ditto [RX] */
+/*-------------------------------------------------------------------*/
+DEF_INST( tcpip )
+{
+ int r1; /* Value of R field */
+ int b2; /* Base of effective addr */
+ VADR effective_addr2; /* Effective address */
+ int i;
+ unsigned char * s;
+
+ /* vv---vv---------------- input variables to TCPIP */
+ RX(inst, regs, r1, b2, effective_addr2);
+ /* ^^-- becomes yyy+gr[b]+gr[c] */
+ /* ^^------ becomes access register c */
+ /* ^^---------- becomes to-store register a */
+
+ if (!FACILITY_ENABLED( HERC_TCPIP_PROB_STATE, regs )) PRIV_CHECK(regs);
+
+ if (regs->GR_L(0) == 0) { /* Only run when R0 = 0, (restart) */
+
+ if (lar_tcpip (&(regs->gr [0])) == 0) { /* Get PC buffer */
+ regs->GR_L(15) = -1; /* Error */
+ return;
+ }
+
+ regs->GR_L(0) = 1; /* Do not call native routine again */
+ }
+
+ if (regs->GR_L(1) != 0) s = (unsigned char *)(map32[regs->GR_L(2)]);
+
+ while (regs->GR_L(1) != 0) { /* Finished > */
+
+ i = regs->GR_L(1) - 1;
+ if (i > 255) i = 255;
+
+ if (regs->GR_L(3) == 0) { /* Going to host */
+ /* Load bytes from operand address */
+ ARCH_DEP(vfetchc) ( s, (unsigned char)i, effective_addr2, b2, regs );
+ } else { /* Going from host */
+ /* Store bytes at operand address */
+ ARCH_DEP(vstorec) ( s, (unsigned char)i, effective_addr2, b2, regs );
+ }
+
+ i++;
+ effective_addr2 += i; /* No exception, quick copy without calc's */
+ (regs->GR_L(b2)) += i; /* Exception, can recalculate if/when restart */
+ s += i; /* Next PC byte segment location */
+ (regs->GR_L(1)) -= i; /* One less segment to copy next time */
+ }
+
+ if (lar_tcpip (&(regs->gr [0])) == 0) { /* Run! */
+ regs->GR_L(15) = -1; /* Error */
+ return;
+ }
+
+ regs->GR_L(15) = 0; /* No error */
+}
+#endif /*defined( FEATURE_TCPIP_EXTENSION )*/
+
+#if !defined( _GEN_ARCH )
+ #if defined( _ARCH_NUM_1 )
+ #define _GEN_ARCH _ARCH_NUM_1
+ #include "x75.c"
+ #endif
+ #if defined( _ARCH_NUM_2 )
+ #undef _GEN_ARCH
+ #define _GEN_ARCH _ARCH_NUM_2
+ #include "x75.c"
+ #endif
+#endif /*!defined( _GEN_ARCH )*/
diff --git a/x75.h b/x75.h
new file mode 100644
index 000000000..cc54ff290
--- /dev/null
+++ b/x75.h
@@ -0,0 +1,8 @@
+/*-------------------------------------------------------------------*/
+/* X75.H (C) Copyright Jason Paul Winter, 2003,2010 */
+/* Minor adaptions for SDL Hyperion, Juergen Winkelmann 2019 */
+/*-------------------------------------------------------------------*/
+
+extern int lar_tcpip (DW * regs); /* function in tcpip.c */
+extern ULONG_PTR map32[Ccom]; /* map 64-bit host addresses */
+ /* to 32-bit guest registers */