home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxsvm10.zip / rxsockvm.c next >
C/C++ Source or Header  |  2000-08-01  |  76KB  |  2,564 lines

  1. /*********************************************************************/
  2. /*                                     */
  3. /* Module:    RxSockVM                          */
  4. /*                                     */
  5. /* Author:      Peter Flass <Flass@Leginfo.LBDC.State.NY.US>         */
  6. /*                                     */
  7. /* Function:    OS/2 Rexx Sockets library compatible with VM/ESA     */
  8. /*              Version 2 Release 3.0 and higher                     */
  9. /*                                     */
  10. /* Date:    14 Jul, 2000                           */
  11. /*                                     */
  12. /* Version:    1.0                             */
  13. /*                                     */
  14. /* OS Version:    OS/2 Warp 4.0, TCP/IP version 4                 */
  15. /*              EMX 0.9d ** Uses emx sockets, not OS/2 sockets       */
  16. /*                                     */
  17. /* Unimplemented Functions return EINVALIDRXSOCKETCALL:              */
  18. /*   (not supported by underlying OS/2 TCP/IP)                       */
  19. /*    GiveSocket                                                     */
  20. /*    TakeSocket                                                     */
  21. /*    Trace                                                          */
  22. /*                                     */
  23. /*********************************************************************/
  24.  
  25. #define  VERSION "RxSockVM 1.00 14 July 2000"
  26.  
  27. #define  MAX_DIGITS     9          /* maximum digits in numeric arg  */
  28.  
  29. #define  EINVALIDRXSOCKETCALL 2001
  30. #define  ESUBTASKNOTACTIVE    2005
  31. #define  EMAXSOCKETSREACHED   2007
  32.  
  33. typedef  struct sockaddr_in *PSOCKADDR;
  34.  
  35. #define INCL_REXXSAA
  36. #include <os2.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <errno.h>
  41. #include <limits.h>
  42. #include <fcntl.h>
  43. #include <sys/time.h>
  44. #include <sys/types.h>
  45. #include <sys/socket.h>
  46. #include <sys/ioctl.h>
  47. #include <netinet/in.h>
  48. #include <netdb.h>
  49.  
  50. /*-------------------------*/
  51. /* Internal Function Defs  */
  52. /*-------------------------*/
  53. INT soaccept();
  54. INT sobind();
  55. INT socls();
  56. INT soconn();
  57. INT sofcntl();
  58. INT sogetclid();
  59. INT sogetdom();
  60. INT sogethba();
  61. INT sogethbn();
  62. INT sogethid();
  63. INT sogethn();
  64. INT sogetpeer();
  65. INT sogetpbynam();
  66. INT sogetpbynum();
  67. INT sogetsbyn();
  68. INT sogetsbyp();
  69. INT sogetsnam();
  70. INT sogetsopt();
  71. INT soinit();
  72. INT soioctl();
  73. INT solisten();
  74. INT soread();
  75. INT sorecv();
  76. INT sorecvfr();
  77. INT soresolv();
  78. INT sosel();
  79. INT sosend();
  80. INT sosendto();
  81. INT sosetsopt();
  82. INT sosocket();
  83. INT soset();
  84. INT sossl();
  85. INT sosss();
  86. INT soshut();
  87. INT soterm();
  88. INT sotrans();
  89. INT sovers();
  90. INT sowrite();
  91. INT sounimpl();
  92.  
  93. RexxFunctionHandler Socket;
  94.  
  95. /*-------------------------*/
  96. /* Socket Table - Internal */
  97. /*-------------------------*/
  98. typedef struct {
  99.    INT stab_snum;
  100.    INT stab_satt;
  101.    } STAB, *PSTAB;
  102. /* stab_satt=0 ASCII  */
  103. /* stab_satt=1 EBCDIC */
  104. LONG  maxsockets = 0;
  105. INT   nsock = 0;
  106. PSTAB ps;
  107.  
  108. CHAR Subtaskid[9] = "";
  109.  
  110. /*-------------------------*/
  111. /* Command table           */
  112. /*-------------------------*/
  113. static const PCH fns[] = { 
  114.   "ACCEPT",         "BIND",             "CLOSE",           "CONNECT", 
  115.   "FCNTL",          "GETCLIENTID",      "GETDOMAINNAME",   "GETHOSTBYADDR", 
  116.   "GETHOSTBYNAME",  "GETHOSTID",        "GETHOSTNAME",     "GETPEERNAME",
  117.   "GETPROTOBYNAME", "GETPROTOBYNUMBER", "GETSERVBYNAME",   "GETSERVBYPORT",
  118.   "GETSOCKNAME",    "GETSOCKOPT",       "GIVESOCKET",      "INITIALIZE",
  119.   "IOCTL",          "LISTEN",           "READ",            "RECV",
  120.   "RECVFROM",       "RESOLVE",          "SELECT",          "SEND",
  121.   "SENDTO",         "SETSOCKOPT",       "SHUTDOWN",        "SOCKET",
  122.   "SOCKETSET",      "SOCKETSETLIST",    "SOCKETSETSTATUS", "TAKESOCKET",
  123.   "TERMINATE",      "TRACE",            "TRANSLATE",       "VERSION",
  124.   "WRITE",          (PCH)NULL  };
  125.  
  126. /*-------------------------*/
  127. /* Internal function names */
  128. /*-------------------------*/
  129. static const PFN fne[] = { 
  130.    (PFN)&soaccept,   (PFN)&sobind,      (PFN)&socls,      (PFN)&soconn,
  131.    (PFN)&sofcntl,    (PFN)&sogetclid,   (PFN)&sogetdom,   (PFN)&sogethba,
  132.    (PFN)&sogethbn,   (PFN)&sogethid,    (PFN)&sogethn,    (PFN)&sogetpeer,
  133.    (PFN)&sogetpbynam,(PFN)&sogetpbynum, (PFN)&sogetsbyn,  (PFN)&sogetsbyp,
  134.    (PFN)&sogetsnam,  (PFN)&sogetsopt,   (PFN)&sounimpl,   (PFN)&soinit,
  135.    (PFN)&soioctl,    (PFN)&solisten,    (PFN)&soread,     (PFN)&sorecv,
  136.    (PFN)&sorecvfr,   (PFN)&soresolv,    (PFN)&sosel,      (PFN)&sosend,
  137.    (PFN)&sosendto,   (PFN)&sosetsopt,   (PFN)&soshut,     (PFN)&sosocket,
  138.    (PFN)&soset,      (PFN)&sossl,       (PFN)&sosss,      (PFN)&sounimpl,
  139.    (PFN)&soterm,     (PFN)&sounimpl,    (PFN)&sotrans,    (PFN)&sovers,
  140.    (PFN)&sowrite  };
  141.  
  142. /*-------------------------*/
  143. /* Minimum # of arguments  */
  144. /*-------------------------*/
  145. static const INT argmin[] = {
  146.    2,            3,        2,        3,
  147.    3,            1,        1,        2,
  148.    2,            1,        1,        2,
  149.    2,            2,        2,        2,
  150.    2,            4,        3,        2,
  151.    3,            2,        2,        2,
  152.    2,            2,        1,        3,
  153.    3,            5,        2,        1,
  154.    1,            1,        1,        3,
  155.    1,            1,        3,        1,
  156.    3,            0 };
  157.  
  158. /*-------------------------*/
  159. /* Maximum # of arguments  */
  160. /*-------------------------*/
  161. static const INT argmax[] = {
  162.    2,            3,        2,        3,
  163.    4,            2,        1,        2,
  164.    2,            1,        1,        2,
  165.    2,            2,        3,        3,
  166.    2,            4,        3,        4,
  167.    4,            3,        3,        4,
  168.    4,            3,            3,        4,
  169.    5,            5,        3,        4,
  170.    2,            1,        2,        3,
  171.    2,            2,        3,        1,
  172.    3,            0 };
  173.  
  174. /*-------------------------*/
  175. /* Address Families        */
  176. /*-------------------------*/
  177. static const PSZ fam[AF_MAX] = { 
  178.   "AF_UNSPEC",      "AF_UNIX",          "AF_INET",    "AF_IMPLINK",
  179.   "AF_PUP",        "AF_CHAOS",        "AF_NS",    "AF_OSI",
  180.   "AF_ECMA",        "AF_DATAKIT",    "AF_CCITT",    "AF_SNA",
  181.   "AF_DECNET",        "AF_DLI",        "AF_LAT",    "AF_HYLINK",
  182.   "AF_APPLETALK",   "AF_NETBIOS" };
  183.  
  184. /*-------------------------*/
  185. /* Socket Types            */
  186. /*-------------------------*/
  187. #define TYPE_MAX 4
  188. static const PSZ typ[TYPE_MAX] = { 
  189.   "SOCK_STREAM",    "SOCK_DGRAM",       "SOCK_RAW",    "RAW" };    
  190.  
  191. /*-------------------------*/
  192. /* Socket Options          */
  193. /* (combo of OS/2 and VM)  */
  194. /*-------------------------*/
  195. #define OPT_MAX 20
  196. #define SO_ASCII  -1
  197. #define SO_EBCDIC -2
  198. static const PSZ opt[OPT_MAX] = { 
  199.   "SO_BROADCAST",   "SO_ERROR",         "SO_KEEPALIVE", "SO_LINGER",
  200.   "SO_OOBINLINE",   "SO_REUSEADDR",    "SO_SNDBUF",    "SO_TYPE",
  201.   "SO_ASCII",       "SO_EBCDIC",        "SO_DEBUG",    "SO_DONTROUTE",
  202.   "SO_RCVBUF",        "SO_RCVLOWAT",    "SO_RCVTIMEO",    "SO_SNDBUF",
  203.   "SO_SNDLOWAT",    "SO_SNDTIMEO",    "SO_TYPE",    "SO_USELOOPBACK"
  204.   };
  205.  
  206. /*-------------------------*/
  207. /* Descriptive error codes */
  208. /*-------------------------*/
  209. static const PSZ perrx[] = {
  210.    "EPERM",   "ENOENT", "ESRCH",   "EINTR",  "EIO",
  211.    "ENXIO",   "E2BIG",  "ENOEXEC", "EBADF",  "ECHILD",
  212.    "EAGAIN",  "ENOMEM", "EACCES",  "EFAULT", "ENOLCK",
  213.    "EBUSY",   "EEXIST", "EXDEV",   "ENODEV", "ENOTDIR",
  214.    "EISDIR",  "EINVAL", "ENFILE",  "EMFILE", "ENOTTY",
  215.    "EDEADLK", "EFBIG",  "ENOSPC",  "ESPIPE", "EROFS",
  216.    "EMLINK",  "EPIPE",  "EDOM",    "ERANGE", "ENOTEMPTY",
  217.    "EINPROGRESS",       "ENOSYS",            "ENAMETOOLONG",
  218.    "EDESTADDRREQ",      "EMSGSIZE",          "EPROTOTYPE",
  219.    "ENOPROTOOPT",       "EPROTONOSUPPORT",   "ESOCKTNOSUPPORT",
  220.    "EOPNOTSUPP",        "EPFNOSUPPORT",      "EAFNOSUPPORT",
  221.    "EADDRINUSE",        "EADDRNOTAVAIL",     "ENETDOWN",
  222.    "ENETUNREACH",       "ENETRESET",         "ECONNABORTED",
  223.    "ECONNRESET",        "ENOBUFS",           "EISCONN",
  224.    "ENOTCONN",          "ESHUTDOWN",         "ETOOMANYREFS",
  225.    "ETIMEDOUT",         "ECONNREFUSED",      "ELOOP",
  226.    "ENOTSOCK",          "EHOSTDOWN",         "EHOSTUNREACH",
  227.    "EALREADY"  
  228.    };
  229.  
  230. static const INT optx[OPT_MAX] = {
  231.    SO_BROADCAST,     SO_ERROR,           SO_KEEPALIVE,   SO_LINGER, 
  232.    SO_OOBINLINE,     SO_REUSEADDR,      SO_SNDBUF,      SO_TYPE,
  233.    SO_ASCII,         SO_EBCDIC,          SO_DEBUG,     SO_DONTROUTE,
  234.    SO_RCVBUF,         SO_RCVLOWAT,     SO_RCVTIMEO,     SO_SNDBUF,
  235.    SO_SNDLOWAT,         SO_SNDTIMEO,     SO_TYPE,     SO_USELOOPBACK
  236.    };
  237.  
  238. /*-------------------------------------------------*/
  239. /* STANDARD translate table copied from OS/390 TCP */
  240. /*-------------------------------------------------*/
  241. /* tcplxbin: ascii to ebcdic */
  242. static UCHAR A2E[] = {
  243.   0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
  244.   0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
  245.   0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
  246.   0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x35, 0x1F,
  247.   0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
  248.   0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
  249.   0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  250.   0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
  251.   0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
  252.   0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
  253.   0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
  254.   0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
  255.   0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  256.   0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
  257.   0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
  258.   0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
  259.   0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
  260.   0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
  261.   0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
  262.   0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x35, 0x1F,
  263.   0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
  264.   0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
  265.   0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  266.   0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
  267.   0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
  268.   0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
  269.   0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
  270.   0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
  271.   0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  272.   0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
  273.   0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
  274.   0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07 };
  275.  
  276. /* tcplxbin: ebcdic to ascii */
  277. static UCHAR E2A[] = {
  278.   0x00, 0x01, 0x02, 0x03, 0x1A, 0x09, 0x1A, 0x7F,
  279.   0x1A, 0x1A, 0x1A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
  280.   0x10, 0x11, 0x12, 0x13, 0x1A, 0x0A, 0x08, 0x1A,
  281.   0x18, 0x19, 0x1A, 0x1A, 0x1C, 0x1D, 0x1E, 0x1F,
  282.   0x1A, 0x1A, 0x1C, 0x1A, 0x1A, 0x0A, 0x17, 0x1B,
  283.   0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x05, 0x06, 0x07,
  284.   0x1A, 0x1A, 0x16, 0x1A, 0x1A, 0x1E, 0x1A, 0x04,
  285.   0x1A, 0x1A, 0x1A, 0x1A, 0x14, 0x15, 0x1A, 0x1A,
  286.   0x20, 0xA6, 0xE1, 0x80, 0xEB, 0x90, 0x9F, 0xE2,
  287.   0xAB, 0x8B, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
  288.   0x26, 0xA9, 0xAA, 0x9C, 0xDB, 0xA5, 0x99, 0xE3,
  289.   0xA8, 0x9E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
  290.   0x2D, 0x2F, 0xDF, 0xDC, 0x9A, 0xDD, 0xDE, 0x98,
  291.   0x9D, 0xAC, 0xBA, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
  292.   0xD7, 0x88, 0x94, 0xB0, 0xB1, 0xB2, 0xFC, 0xD6,
  293.   0xFB, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
  294.   0xF8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  295.   0x68, 0x69, 0x96, 0xA4, 0xF3, 0xAF, 0xAE, 0xC5,
  296.   0x8C, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
  297.   0x71, 0x72, 0x97, 0x87, 0xCE, 0x93, 0xF1, 0xFE,
  298.   0xC8, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  299.   0x79, 0x7A, 0xEF, 0xC0, 0xDA, 0x5B, 0xF2, 0xF9,
  300.   0xB5, 0xB6, 0xFD, 0xB7, 0xB8, 0xB9, 0xE6, 0xBB,
  301.   0xBC, 0xBD, 0x8D, 0xD9, 0xBF, 0x5D, 0xD8, 0xC4,
  302.   0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  303.   0x48, 0x49, 0xCB, 0xCA, 0xBE, 0xE8, 0xEC, 0xED,
  304.   0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
  305.   0x51, 0x52, 0xA1, 0xAD, 0xF5, 0xF4, 0xA3, 0x8F,
  306.   0x5C, 0xE7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
  307.   0x59, 0x5A, 0xA0, 0x85, 0x8E, 0xE9, 0xE4, 0xD1,
  308.   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  309.   0x38, 0x39, 0xB3, 0xF7, 0xF0, 0xFA, 0xA7, 0xFF };
  310.  
  311.  
  312.  
  313. /*-----------------------------------*/
  314. /* Generate Error message            */
  315. /*-----------------------------------*/
  316. void soerr( PRXSTRING r, ULONG err ) {
  317.    PCH p;
  318.    p = r->strptr;
  319.    p+= sprintf( p, "%d ", err );
  320.    switch(err) {
  321.       case EINVALIDRXSOCKETCALL:
  322.          p+= sprintf( p, "EINVALIDRXSOCKETCALL Syntax error in RXSOCKET parameter list" );
  323.          break;
  324.       case ESUBTASKNOTACTIVE:
  325.          p+= sprintf( p, "ESUBTASKNOTACTIVE Subtask not active" );
  326.          break;
  327.       case EMAXSOCKETSREACHED:
  328.          p+= sprintf( p, "EMAXSOCKETSREACHED Maximum number of sockets reached" );
  329.          break;
  330.       /* NOTE: ===> First string is error code */
  331.       default: 
  332.          if( err<1 || err>EALREADY )
  333.            p+= sprintf( p, "%s %s", " ", strerror(err) );
  334.          else p+= sprintf( p, "%s %s", "*", perrx[err], strerror(err) );
  335.          break;
  336.       }
  337.    r->strlength = strlen(r->strptr);
  338.    return;
  339.    } /* End soerr */
  340.  
  341. /*-----------------------------------*/
  342. /* Convert a Rexx string to a LONG   */
  343. /*-----------------------------------*/
  344. BOOL string2long(PRXSTRING str, LONG *num)
  345. {
  346.   ULONG    accumulator;                /* converted number           */
  347.   INT      length;                     /* length of number           */
  348.   INT      sign;                       /* sign of number             */
  349.   PCH      string;               /* -> String                  */
  350.  
  351.   if( RXNULLSTRING(*str) || RXZEROLENSTRING(*str) ) {
  352.      return FALSE;
  353.      }
  354.  
  355.   length = str->strlength;
  356.   string = str->strptr;
  357.   sign = 1;                            /* set default sign           */
  358.   if (*string == '-') {                /* negative?                  */
  359.     sign = -1;                         /* change sign                */
  360.     string++;                          /* step past sign             */
  361.     length--;                   /* decrement length         */
  362.   }
  363.  
  364.   if (length == 0 ||                   /* if null string             */
  365.       length > MAX_DIGITS)             /* or too long                */
  366.     return FALSE;                      /* not valid                  */
  367.  
  368.   accumulator = 0;                     /* start with zero            */
  369.  
  370.   while (length) {                     /* while more digits          */
  371.     if (!isdigit(*string))             /* not a digit?               */
  372.       return FALSE;                    /* tell caller                */
  373.                                        /* add to accumulator         */
  374.     accumulator = accumulator *10 + (*string - '0');
  375.     length--;                          /* reduce length              */
  376.     string++;                          /* step pointer               */
  377.   }
  378.   *num = accumulator * sign;           /* return the value           */
  379.   return TRUE;                         /* good number                */
  380. } /* End string2long */
  381.  
  382. /*-----------------------------------*/
  383. /* Extract a number from a field     */
  384. /*-----------------------------------*/
  385. INT getint(PCH p, INT l )
  386. {
  387.   INT      accumulator;                /* converted number           */
  388.   INT      sign;                       /* sign of number             */
  389.  
  390.   sign = 1;                            /* set default sign           */
  391.   if (*p == '-') {                     /* negative?                  */
  392.     sign = -1;                         /* change sign                */
  393.     p++;                               /* step past sign             */
  394.     l--;                   /* decrement length         */
  395.   }
  396.  
  397.   if (l == 0 || l > 5 )                /* if null string or too long */
  398.     return INT_MIN;                    /* not valid                  */
  399.  
  400.   accumulator = 0;                     /* start with zero            */
  401.  
  402.   while (l) {                          /* while more digits          */
  403.     if (!isdigit(*p))                  /* not a digit?               */
  404.       return INT_MIN;                  /* tell caller                */
  405.                                        /* add to accumulator         */
  406.     accumulator = accumulator *10 + (*p - '0');
  407.     l--;                               /* reduce length              */
  408.     p++;                               /* step pointer               */
  409.   }
  410.   return accumulator * sign;           /* good number                */
  411. } /* End getint */        
  412.  
  413. /*-----------------------------------*/
  414. /* Parse an address parameter        */
  415. /* 'domain portid ipaddress'         */
  416. /*-----------------------------------*/
  417. BOOL parseaddress(PRXSTRING s, PSOCKADDR paddr)
  418. {
  419.   INT l;
  420.   PUCHAR p,q;
  421.   struct hostent *pHE;
  422.  
  423.   if( RXNULLSTRING(*s) || RXZEROLENSTRING(*s) ) {
  424.      return FALSE;
  425.      }
  426.  
  427.   /*-----------------------*/
  428.   /*  Parse Domain         */
  429.   /*-----------------------*/
  430.   p = s->strptr;
  431.   q = strchr(p,' ');
  432.   if( q==NULL ) return(FALSE);
  433.   l = q-p;
  434.   if( (strnicmp(p,"AF_INET",l)==0) || (strncmp(p,"2",l)==0) )
  435.      paddr->sin_family = AF_INET;
  436.   else return(FALSE);
  437.  
  438.   /*-----------------------*/
  439.   /*  Parse Port           */
  440.   /*-----------------------*/
  441.   for(;*q==' ';q++) /* continue */ ;
  442.   p = q;
  443.   q = strchr(p,' ');
  444.   l = q-p;
  445.   l = getint(p,l);                     /* Get an integer             */
  446.   if( l==INT_MIN ) return FALSE;       /* Bad number                 */
  447.   paddr->sin_port = htons(l); 
  448.  
  449.   /*-----------------------*/
  450.   /*  Parse IP Address     */
  451.   /*-----------------------*/
  452.   for(;*q==' ';q++) /* continue */ ;
  453.   p = q;
  454.   q = strchr(p,' ');
  455.   if( q==NULL ) q=p+strlen(p);
  456.   l = q-p;
  457.   if( isdigit(*p) ) {                  /* numeric IP address         */
  458.      paddr->sin_addr.s_addr = inet_addr(p);
  459.      }
  460.   else {                               /* Alphanumeric host name     */
  461.      if( stricmp(p,"INADDR_ANY")==0 ) 
  462.         paddr->sin_addr.s_addr = INADDR_ANY;
  463.      else if( stricmp(p,"INADDR_BROADCAST")==0  )
  464.         paddr->sin_addr.s_addr = INADDR_BROADCAST;
  465.      else {
  466.         pHE = gethostbyname(p);
  467.         if( pHE==NULL ) return FALSE;
  468.         paddr->sin_addr.s_addr = (ULONG) *(pHE->h_addr);
  469.         }
  470.      }
  471.  
  472.   return TRUE;                         /* good number                */
  473. } /* End parseaddress */
  474.  
  475. /*-----------------------------------*/
  476. /* Extract the next blank-delimited  */
  477. /* word from a string                */
  478. /*-----------------------------------*/
  479. PSZ next_word(PSZ p)
  480. {
  481. } /* end next_word */
  482.  
  483. /*-----------------------------------*/
  484. /* Main Entry point for Socket()     */
  485. /*-----------------------------------*/
  486. ULONG APIENTRY Socket( PCSZ name, ULONG numargs, PRXSTRING argp,
  487.              PCSZ queuename, PRXSTRING rp)
  488.    {
  489.  
  490.    PRXSTRING fp;                        /* -> Function request         */
  491.    PCH       f;
  492.    INT       i;
  493.  
  494.    /*--------------------------------*/
  495.    /* Validate command               */
  496.    /*--------------------------------*/
  497.    if( numargs<1 ) {
  498.       soerr( rp, EINVALIDRXSOCKETCALL  );
  499.       return(0);
  500.       }
  501.    fp = argp;                       /* -> First argument         */
  502.    if( RXNULLSTRING(*fp) ) {
  503.       soerr( rp, EINVALIDRXSOCKETCALL  );
  504.       return(0);
  505.       }
  506.  
  507.    for( i=0; fns[i]!=(PCH)NULL; i++ ) {
  508.       if( fp->strlength != strlen(fns[i]) )  continue;
  509.       if( stricmp(fns[i],fp->strptr)==0 )    break;
  510.       }
  511.    f = fns[i];
  512.    if( f==(PCH)NULL ) {             /* Invalid function                     */
  513.       soerr( rp, EINVALIDRXSOCKETCALL  );
  514.       return(0);
  515.       }
  516.    
  517.    /*--------------------------------*/
  518.    /* Validate number of arguments   */
  519.    /*--------------------------------*/
  520.    if( numargs<argmin[i] ) {
  521.       soerr( rp, EINVALIDRXSOCKETCALL  );
  522.       return(0);
  523.       }
  524.    if( (argmax[i]>0) && (numargs>argmax[i]) ) {
  525.       soerr( rp, EINVALIDRXSOCKETCALL  );
  526.       return(0);
  527.       }
  528.  
  529.    /*--------------------------------*/
  530.    /* Execute command                */
  531.    /*--------------------------------*/
  532.    fp = (PRXSTRING)( (PUCHAR)fp + sizeof(RXSTRING) );
  533.    (INT)(*fne[i])( numargs, fp, rp );
  534.  
  535.    return(0);
  536.  
  537.    } /* End Socket */
  538.  
  539.  
  540. /*-----------------------------------*/
  541. /* ACCEPT Function (0)               */
  542. /*-----------------------------------*/
  543. INT soaccept( ULONG n, PRXSTRING a, PRXSTRING r ) {
  544.    struct sockaddr_in addr;
  545.    INT    addrl;
  546.    INT    so;
  547.    LONG   s;
  548.    PCH    p;
  549.  
  550.    if( string2long(a,&s)==FALSE ) {
  551.       soerr( r, EINVALIDRXSOCKETCALL  );
  552.       return(0);
  553.       }
  554.  
  555.    addrl = sizeof(addr);
  556.    so = accept( s, (struct sockaddr *)&addr, &addrl );
  557.    if( so<0 ) {
  558.       soerr( r, errno );
  559.       return 0;
  560.       }
  561.    if( addr.sin_family>=AF_MAX )
  562.       addr.sin_family=AF_UNSPEC;
  563.    p = r->strptr; 
  564.    p += sprintf( p, "0 %d ",so );
  565.    strcat(p,fam[addr.sin_family]);
  566.    p += strlen(p);
  567.    if( addr.sin_family==AF_INET ) {
  568.       p += sprintf( p, " %d %s", ntohs(addr.sin_port),
  569.                    inet_ntoa(addr.sin_addr) );
  570.       } /* End INET */
  571.    *p='\0';
  572.    r->strlength = strlen(r->strptr);
  573.    return(0);
  574.    } /* End soaccept */
  575.  
  576. /*-----------------------------------*/
  577. /* BIND Function (1)                 */
  578. /*-----------------------------------*/
  579. INT sobind( ULONG n, PRXSTRING a, PRXSTRING r ) {
  580.    struct sockaddr_in addr;
  581.    INT    addrl;
  582.    INT    so;
  583.    LONG   s;
  584.    PUCHAR pAddr;
  585.    PRXSTRING arg3;
  586.  
  587.    if( string2long(a,&s)==FALSE ) {
  588.       soerr( r, EINVALIDRXSOCKETCALL );
  589.       return(0);
  590.       }
  591.  
  592.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  593.    addrl = sizeof(addr);
  594.    if( parseaddress(arg3,&addr)!=TRUE ) {
  595.       soerr( r, EINVALIDRXSOCKETCALL  );
  596.       return(0);
  597.       }
  598.    so = bind( s, (struct sockaddr *)&addr, addrl );
  599.    if( so<0 ) {
  600.       soerr( r, errno );
  601.       }
  602.    else strcpy( r->strptr, "0" );
  603.    r->strlength = strlen(r->strptr);
  604.    return(0);
  605.    } /* End sobind */
  606.  
  607. /*-----------------------------------*/
  608. /* CLOSE Function (2)                */
  609. /*-----------------------------------*/
  610. INT socls( ULONG n, PRXSTRING a, PRXSTRING r ) {
  611.    INT    rc;
  612.    LONG   s;
  613.    INT    i,j;
  614.    PSTAB  pst,qst;
  615.  
  616.    if( string2long(a,&s)==FALSE ) {
  617.       soerr( r, EINVALIDRXSOCKETCALL  );
  618.       return(0);
  619.       }
  620.  
  621.    /*----------------------*/
  622.    /* Del socket from list */
  623.    /*----------------------*/
  624.    pst = ps;
  625.    for( i=1; i<=nsock; i++ ) {
  626.       if( pst->stab_snum==s ) break;
  627.       pst = (PSTAB)( (PUCHAR)pst + sizeof(STAB) );
  628.       }
  629.    if( i>nsock ) {
  630.       soerr( r, EINVALIDRXSOCKETCALL  );
  631.       return(0);
  632.       }
  633.    for( j=i+1; j<=nsock; j++,i++ ) {
  634.       qst = (PSTAB)( (PUCHAR)pst + sizeof(STAB) );
  635.       qst->stab_snum = pst->stab_snum;
  636.       qst->stab_satt = pst->stab_satt;
  637.       pst = qst;
  638.       }
  639.    nsock--;
  640.  
  641.    rc = close( s );
  642.    if( rc<0 ) {
  643.       soerr( r, errno );
  644.       }
  645.    else strcpy( r->strptr, "0" );
  646.    r->strlength = strlen(r->strptr);
  647.    return(0);
  648.    } /* End socls */
  649.  
  650. /*-----------------------------------*/
  651. /* CONNECT Function (3)              */
  652. /*-----------------------------------*/
  653. INT soconn( ULONG n, PRXSTRING a, PRXSTRING r ) {
  654.    struct sockaddr_in addr;
  655.    INT    addrl;
  656.    INT    rc;
  657.    LONG   s;
  658.    PRXSTRING arg3;
  659.  
  660.    if( string2long(a,&s)==FALSE ) {
  661.       soerr( r, EINVALIDRXSOCKETCALL  );
  662.       return(0);
  663.       }
  664.  
  665.    addrl = sizeof(addr);
  666.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  667.    if( parseaddress(arg3,&addr)==FALSE ) {
  668.       soerr( r, EINVALIDRXSOCKETCALL  );
  669.       return(0);
  670.       }
  671.  
  672.    rc = connect( s, (struct sockaddr *)&addr, addrl );
  673.  
  674.    if( rc<0 ) {
  675.       soerr( r, errno );
  676.       }
  677.    else strcpy( r->strptr, "0" );
  678.    r->strlength = strlen(r->strptr);
  679.    return(0);
  680.    } /* End soconn */
  681.  
  682. /*-----------------------------------*/
  683. /* FCNTL Function (4)                */
  684. /*-----------------------------------*/
  685. INT sofcntl( ULONG n, PRXSTRING a, PRXSTRING r ) {
  686.    INT    so;
  687.    LONG   s;
  688.    PRXSTRING arg3,arg4;
  689.    INT    fcntl_arg=0;
  690.  
  691.    if( string2long(a,&s)==FALSE ) {
  692.       soerr( r, EINVALIDRXSOCKETCALL  );
  693.       return(0);
  694.       }
  695.  
  696.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  697.    if( RXNULLSTRING(*arg3) || RXZEROLENSTRING(*arg3) ) {
  698.       soerr( r, EINVALIDRXSOCKETCALL  );
  699.       return(0);
  700.       }
  701.    if( stricmp(arg3->strptr,"F_GETFL")==0 ) {
  702.       fcntl_arg = fcntl(s,F_GETFL);
  703.       if( fcntl_arg==-1 ) {
  704.          soerr( r, errno );
  705.          return(0);
  706.          }
  707.       if( (fcntl_arg&O_NONBLOCK)!=0 )
  708.          strcpy( r->strptr, "0 NON-BLOCKING");
  709.       else strcpy( r->strptr, "0 BLOCKING");
  710.       r->strlength = strlen(r->strptr);
  711.       return(0);
  712.       }
  713.    else if( stricmp(arg3->strptr,"F_SETFL")==0 ) {
  714.       if( n<4 ) {
  715.          soerr( r, EINVALIDRXSOCKETCALL  );
  716.          return(0);
  717.          }
  718.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  719.       if( RXNULLSTRING(*arg4) || RXZEROLENSTRING(*arg4) ) {
  720.          soerr( r, EINVALIDRXSOCKETCALL  );
  721.          return(0);
  722.          }
  723.       if( (stricmp(arg4->strptr,"NON-BLOCKING")==0) ||
  724.           (stricmp(arg4->strptr,"FNDELAY")==0) ) 
  725.          fcntl_arg = O_NONBLOCK;
  726.       else if( (stricmp(arg4->strptr,"BLOCKING")==0) ||
  727.                (stricmp(arg4->strptr,"0")==0) ) 
  728.          fcntl_arg = -1&(~O_NONBLOCK);
  729.       else {
  730.          soerr( r, EINVALIDRXSOCKETCALL  );
  731.          return(0);
  732.          }
  733.       if( fcntl(s,F_SETFL,fcntl_arg)==-1 ) {
  734.          soerr( r, errno );
  735.          return(0);
  736.          }
  737.       strcpy( r->strptr, "0" );
  738.       r->strlength = strlen(r->strptr);
  739.       return(0);
  740.       }
  741.    else {
  742.       soerr( r, EINVALIDRXSOCKETCALL  );
  743.       return 0;
  744.       }
  745.    } /* End sofcntl */
  746.  
  747. /*-----------------------------------*/
  748. /* GETCLIENTID Function (5)          */
  749. /*-----------------------------------*/
  750. INT sogetclid( ULONG n, PRXSTRING a, PRXSTRING r ) {
  751.  
  752.    if( RXNULLSTRING(*a) || RXZEROLENSTRING(*a) ) {
  753.       soerr( r, EINVALIDRXSOCKETCALL  );
  754.       return(0);
  755.       }
  756.  
  757.    if( n>1 ) {
  758.       if( (stricmp(a->strptr,"AF_INET")==0)  ||
  759.           (stricmp(a->strptr,"AF_UNSPEC")==0)||
  760.           (strcmp(a->strptr,"0")==0)         ||
  761.           (strcmp(a->strptr,"2")==0) ) /* continue */ ;
  762.       else {
  763.          soerr( r, EINVALIDRXSOCKETCALL  );
  764.          return 0;
  765.          } 
  766.       } /* end n>1 */
  767.       
  768.    sprintf( r->strptr,"0 AF_INET  %8s %8s","Userid",Subtaskid);
  769.    /* NOTE: TCP/IP "Userid" value */
  770.    r->strlength = strlen(r->strptr);
  771.    return(0);
  772.    } /* End sogetclid */
  773.  
  774. /*-----------------------------------*/
  775. /* GETDOMAINNAME Function (6)        */
  776. /*-----------------------------------*/
  777. INT sogetdom( ULONG n, PRXSTRING a, PRXSTRING r ) {
  778.    struct in_addr host_addr;
  779.    struct hostent *pHE;
  780.    PCH    p;
  781.  
  782.    host_addr.s_addr = htonl( gethostid() );
  783.    pHE = gethostbyaddr( (PCH)&host_addr, sizeof(struct in_addr) , AF_INET );
  784.  
  785.    if( pHE==NULL ) {
  786.       soerr( r, h_errno );
  787.       return(0);
  788.       }
  789.    p = strchr(pHE->h_name,'.');
  790.    if( p!=NULL ) p++;
  791.    sprintf( r->strptr, "0 %s",p );
  792.    r->strlength = strlen(r->strptr);
  793.    return(0);
  794.    } /* End sogetdom */
  795.  
  796. /*-----------------------------------*/
  797. /* GETHOSTBYADDR Function (7)        */
  798. /*-----------------------------------*/
  799. INT sogethba( ULONG n, PRXSTRING a, PRXSTRING r ) {
  800.    struct in_addr host_addr;
  801.    struct hostent *pHE;
  802.  
  803.    if( RXNULLSTRING(*a) || RXZEROLENSTRING(*a) ) {
  804.       soerr( r, EINVALIDRXSOCKETCALL  );
  805.       return(0);
  806.      }
  807.    host_addr.s_addr = inet_addr(a->strptr);
  808.    pHE = gethostbyaddr( (PCH)&host_addr, sizeof(struct in_addr) , AF_INET );
  809.  
  810.    if( pHE==NULL ) {
  811.       soerr( r, h_errno );
  812.       }
  813.    else sprintf( r->strptr, "0 %s",pHE->h_name );
  814.    r->strlength = strlen(r->strptr);
  815.    return(0);
  816.    } /* End sogethba */
  817.  
  818. /*-----------------------------------*/
  819. /* GETHOSTBYNAME Function (8)        */
  820. /*-----------------------------------*/
  821. INT sogethbn( ULONG n, PRXSTRING a, PRXSTRING r ) {
  822.    struct in_addr host_addr;
  823.    struct hostent *pHE;
  824.  
  825.    if( RXNULLSTRING(*a) || RXZEROLENSTRING(*a) ) {
  826.       soerr( r, EINVALIDRXSOCKETCALL  );
  827.       return(0);
  828.      }
  829.    pHE = gethostbyname( a->strptr );
  830.  
  831.    if( pHE==NULL ) {
  832.       soerr( r, h_errno );
  833.       return(0);
  834.       }
  835.    memcpy( &host_addr.s_addr, pHE->h_addr, sizeof host_addr.s_addr );
  836.    sprintf( r->strptr, "0 %s", inet_ntoa(host_addr) );
  837.    r->strlength = strlen(r->strptr);
  838.    return(0);
  839.    } /* End sogethbn */
  840.  
  841. /*-----------------------------------*/
  842. /* GETHOSTID Function (9)            */
  843. /*-----------------------------------*/
  844. INT sogethid( ULONG n, PRXSTRING a, PRXSTRING r ) {
  845.    struct in_addr host_addr;
  846.    PCH    p;
  847.  
  848.    host_addr.s_addr = htonl( gethostid() );
  849.    sprintf( r->strptr, "0 %s", inet_ntoa(host_addr) );
  850.    r->strlength = strlen(r->strptr);
  851.    return(0);
  852.    } /* End sogethid */
  853.  
  854. /*-----------------------------------*/
  855. /* GETHOSTNAME Function (10)         */
  856. /*-----------------------------------*/
  857. INT sogethn( ULONG n, PRXSTRING a, PRXSTRING r ) {
  858.    struct in_addr host_addr;
  859.    struct hostent *pHE;
  860.    PCH    p;
  861.  
  862.    host_addr.s_addr = htonl( gethostid() );
  863.    pHE = gethostbyaddr( (PCH)&host_addr, sizeof(struct in_addr) , AF_INET );
  864.  
  865.    if( pHE==NULL ) {
  866.       soerr( r, h_errno );
  867.       return(0);
  868.       }
  869.    p = strchr(pHE->h_name,'.');
  870.    if( p!=NULL ) *p='\0';       
  871.    sprintf( r->strptr, "0 %s",pHE->h_name );
  872.    r->strlength = strlen(r->strptr);
  873.    return(0);
  874.    } /* End sogethn */
  875.  
  876. /*-----------------------------------*/
  877. /* GETPEERNAME Function (11)         */
  878. /*-----------------------------------*/
  879. INT sogetpeer( ULONG n, PRXSTRING a, PRXSTRING r ) {
  880.    struct in_addr host_addr;
  881.    struct sockaddr_in addr;
  882.    INT    addrl;
  883.    PCH    p;
  884.    LONG   s;
  885.    INT    rc;
  886.  
  887.    if( string2long(a,&s)==FALSE ) {
  888.       soerr( r, EINVALIDRXSOCKETCALL  );
  889.       return(0);
  890.       }
  891.  
  892.    addrl = sizeof(addr);
  893.    rc = getpeername( s, (struct sockaddr *)&addr , &addrl );
  894.  
  895.    if( rc ) {
  896.       soerr( r, errno );
  897.       return(0);
  898.       }
  899.  
  900.    if( addr.sin_family>=AF_MAX )
  901.       addr.sin_family=AF_UNSPEC;
  902.    p = r->strptr; 
  903.    p += sprintf( p, "0 %d ",s );
  904.    strcat(p,fam[addr.sin_family]);
  905.    p += strlen(p);
  906.    if( addr.sin_family==AF_INET ) {
  907.       p += sprintf( p, " %d %s", ntohs(addr.sin_port),
  908.                    inet_ntoa(addr.sin_addr) );
  909.       } 
  910.    *p='\0';
  911.    r->strlength = strlen(r->strptr);
  912.    return(0);
  913.    } /* End sogetpeer */
  914.  
  915. /*-----------------------------------*/
  916. /* GETPROTOBYNAME Function (12)      */
  917. /*-----------------------------------*/
  918. INT sogetpbynam( ULONG n, PRXSTRING a, PRXSTRING r ) {
  919.    INT proto;
  920.  
  921.    if( RXNULLSTRING(*a) || RXZEROLENSTRING(*a) ) {
  922.       soerr( r, EINVALIDRXSOCKETCALL  );
  923.       return(0);
  924.      }
  925.    /* This bypasses the getprotobyname() call, */
  926.    /* since only three protocols are valid.    */
  927.    if( stricmp(a->strptr,"TCP")==0 )      proto = IPPROTO_TCP;
  928.    else if( stricmp(a->strptr,"UDP")==0 ) proto = IPPROTO_UDP;
  929.    else if( stricmp(a->strptr,"IP")==0 )  proto = IPPROTO_IP;
  930.    else {
  931.       strcpy( r->strptr, "0" );
  932.       return(0);
  933.       }
  934.    sprintf( r->strptr, "0 %d", proto );
  935.    r->strlength = strlen(r->strptr);
  936.    return(0);
  937.    } /* End sogetpbynam */
  938.  
  939. /*-----------------------------------*/
  940. /* GETPROTOBYNUM Function (13)       */
  941. /*-----------------------------------*/
  942. INT sogetpbynum( ULONG n, PRXSTRING a, PRXSTRING r ) {
  943.    LONG proto;
  944.    struct protoent *pPE;
  945.  
  946.    if( string2long(a,&proto)==FALSE ) {
  947.       strcpy( r->strptr, "0" );
  948.       return(0);
  949.       }
  950.    pPE = getprotobynumber(proto);
  951.    if( pPE==NULL ) {
  952.       soerr( r, errno );
  953.       return(0);
  954.       }
  955.    sprintf( r->strptr, "0 %s", pPE->p_name );
  956.    r->strlength = strlen(r->strptr);
  957.    return(0);
  958.    } /* End sogetpbynum */
  959.  
  960. /*-----------------------------------*/
  961. /* GETSERVBYNAME Function (14)       */
  962. /*-----------------------------------*/
  963. INT sogetsbyn( ULONG n, PRXSTRING a, PRXSTRING r ) {
  964.    PCH    pProt;
  965.    INT    port;
  966.    struct servent *pSE;
  967.    PRXSTRING arg3;
  968.  
  969.    if( n<3 ) pProt = "";
  970.    else {
  971.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  972.       if( RXNULLSTRING(*arg3) || RXZEROLENSTRING(*arg3) ) {
  973.          soerr( r, EINVALIDRXSOCKETCALL  );
  974.          return(0);
  975.          }
  976.       pProt = arg3->strptr;
  977.       }
  978.    pSE = getservbyname( a->strptr, pProt  );
  979.  
  980.    if( pSE==NULL ) {
  981.       soerr( r, errno );
  982.       return(0);
  983.       }
  984.    sprintf( r->strptr, "0 %s %d %s", pSE->s_name,
  985.             ntohs(pSE->s_port), pSE->s_proto );
  986.    r->strlength = strlen(r->strptr);
  987.    return(0);
  988.    } /* End sogetsbyn */
  989.  
  990. /*-----------------------------------*/
  991. /* GETSERVBYPORT Function (15)       */
  992. /*-----------------------------------*/
  993. INT sogetsbyp( ULONG n, PRXSTRING a, PRXSTRING r ) {
  994.    LONG   p;
  995.    PCH    pProt;
  996.    INT    port;
  997.    struct servent *pSE;
  998.    PRXSTRING arg3;
  999.  
  1000.    if( string2long(a,&p)==FALSE ) {
  1001.       soerr( r, EINVALIDRXSOCKETCALL  );
  1002.       return(0);
  1003.       }
  1004.  
  1005.    if( n<3 ) pProt = "";
  1006.    else {
  1007.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1008.       pProt = arg3->strptr;
  1009.       }
  1010.    pSE = getservbyport( p, pProt  );
  1011.  
  1012.    if( pSE==NULL ) {
  1013.       soerr( r, errno );
  1014.       return(0);
  1015.       }
  1016.    sprintf( r->strptr, "0 %s %d %s", pSE->s_name,
  1017.             ntohs(pSE->s_port), pSE->s_proto );
  1018.    r->strlength = strlen(r->strptr);
  1019.    return(0);
  1020.    } /* End sogetsbyp */
  1021.  
  1022. /*-----------------------------------*/
  1023. /* GETSOCKNAME Function (16)         */
  1024. /*-----------------------------------*/
  1025. INT sogetsnam( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1026.    struct sockaddr_in addr;
  1027.    INT    addrl;
  1028.    PCH    p;
  1029.    LONG   s; 
  1030.    INT    rc;
  1031.  
  1032.    if( string2long(a,&s)==FALSE ) {
  1033.       soerr( r, EINVALIDRXSOCKETCALL );
  1034.       return(0);
  1035.       }
  1036.  
  1037.    addrl = sizeof(addr);
  1038.    rc = getsockname( s, (struct sockaddr *)&addr , &addrl );
  1039.  
  1040.    if( rc ) {
  1041.       soerr( r, errno );
  1042.       return(0);
  1043.       }
  1044.  
  1045.    p = r->strptr; 
  1046.    p += sprintf( p, "0 %s", fam[addr.sin_family] );
  1047.    if( addr.sin_family==AF_INET ) {
  1048.       if( addr.sin_port )
  1049.          p += sprintf( p, " %d", ntohs(addr.sin_port) );
  1050.       if( addr.sin_addr.s_addr )
  1051.          p += sprintf( p, " %s", inet_ntoa(addr.sin_addr) );
  1052.       } 
  1053.    *p='\0';
  1054.    r->strlength = strlen(r->strptr);
  1055.    return(0);
  1056.    } /* End sogetsnam */
  1057.  
  1058. /*-----------------------------------*/
  1059. /* GETSOCKOPT Function (17)          */
  1060. /*-----------------------------------*/
  1061. INT sogetsopt( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1062.    PCH    p;
  1063.    LONG   s; 
  1064.    INT    rc;
  1065.    INT    i,j;
  1066.    PSTAB  pst;
  1067.    PRXSTRING arg3,arg4;
  1068.    char   optbuf[80]; /* Max size buffer */
  1069.    INT    optlen;
  1070.    typedef INT  *POPTINT;
  1071.    typedef LONG *POPTLONG;
  1072.    typedef struct linger *PLINGER;
  1073.  
  1074.    if( string2long(a,&s)==FALSE ) {
  1075.       soerr( r, EINVALIDRXSOCKETCALL );
  1076.       return(0);
  1077.       }
  1078.  
  1079.    /*----------------------*/
  1080.    /* Validate Level       */
  1081.    /*----------------------*/
  1082.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1083.    if( RXNULLSTRING(*arg3) || RXZEROLENSTRING(*arg3) ) {
  1084.       soerr( r, EINVALIDRXSOCKETCALL );
  1085.       return(0);
  1086.       }
  1087.    if( stricmp( arg3->strptr, "SOL_SOCKET" )!=0 ) { 
  1088.       soerr( r, EINVALIDRXSOCKETCALL );
  1089.       return(0);
  1090.       }
  1091.  
  1092.    /*----------------------*/
  1093.    /* Validate Option      */
  1094.    /*----------------------*/
  1095.    arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1096.    if( RXNULLSTRING(*arg4) || RXZEROLENSTRING(*arg4) ) {
  1097.       soerr( r, EINVALIDRXSOCKETCALL  );
  1098.       return(0);
  1099.       }
  1100.    for( i=0; i<OPT_MAX; i++ ) {
  1101.       if( stricmp( arg4->strptr, opt[i] )==0 ) break;
  1102.       }
  1103.    if( i>=OPT_MAX ) {
  1104.       soerr( r, EINVALIDRXSOCKETCALL );
  1105.       return(0);
  1106.       }
  1107.    i = optx[i];
  1108.  
  1109.    /*----------------------*/
  1110.    /* Find Socket          */
  1111.    /*----------------------*/
  1112.    pst = ps;
  1113.    for( j=1; j<=nsock; j++ ) {
  1114.       if( pst->stab_snum==s ) break;
  1115.       pst = (PSTAB)( (PUCHAR)pst + sizeof(STAB) );
  1116.       }
  1117.    if( j>nsock ) {
  1118.       soerr( r, EINVALIDRXSOCKETCALL  );
  1119.       return(0);
  1120.       }
  1121.  
  1122.    /*----------------------*/
  1123.    /* ASCII and EBCDIC are */
  1124.    /* Internal options     */
  1125.    /* Translation table is */
  1126.    /* always "STANDARD"    */
  1127.    /*----------------------*/
  1128.    switch( i ) {
  1129.       case SO_ASCII:
  1130.          p = r->strptr;
  1131.          p+= sprintf( p, "0 %s STANDARD", pst->stab_satt? "On": "Off" );
  1132.          *p='\0';
  1133.          r->strlength = strlen(r->strptr);
  1134.          return(0);
  1135.       case SO_EBCDIC:
  1136.          p = r->strptr;
  1137.          p+= sprintf( p, "0 %s STANDARD", pst->stab_satt? "Off": "On" );
  1138.          *p='\0';
  1139.          r->strlength = strlen(r->strptr);
  1140.          return(0);
  1141.       default: break; 
  1142.       } /* end switch */
  1143.  
  1144.    optlen = sizeof optbuf;
  1145.  
  1146.    rc = getsockopt( s, SOL_SOCKET, i, (PUCHAR)&optbuf, &optlen );
  1147.  
  1148.    if( rc ) {
  1149.       soerr( r, errno );
  1150.       return(0);
  1151.       }
  1152.  
  1153.    p = r->strptr;
  1154.    strcpy( p, "0" ); 
  1155.    p += strlen(p);
  1156.  
  1157.    switch( i ) {
  1158.       case SO_BROADCAST:
  1159.       case SO_DEBUG:
  1160.       case SO_DONTROUTE:
  1161.       case SO_KEEPALIVE:
  1162.       case SO_OOBINLINE:
  1163.       case SO_REUSEADDR:
  1164.          p+= sprintf( p, "%s",optbuf[0]? "On": "Off");
  1165.          break;
  1166.       case SO_ERROR:
  1167.       case SO_TYPE:
  1168.       case SO_USELOOPBACK:
  1169.       case SO_RCVLOWAT:
  1170.       case SO_RCVTIMEO:
  1171.       case SO_SNDLOWAT:
  1172.       case SO_SNDTIMEO:
  1173.          p+= sprintf( p, "%d", (POPTINT)&optbuf);
  1174.          break;
  1175.       case SO_RCVBUF:
  1176.       case SO_SNDBUF:
  1177.          p+= sprintf( p, "%ld", (POPTLONG)&optbuf);
  1178.          break;
  1179.       case SO_LINGER:
  1180.          p+= sprintf( p, "%s %d", ((PLINGER)&optbuf)->l_onoff? "Off": "On",
  1181.                       ((PLINGER)&optbuf)->l_linger);
  1182.          break;
  1183.       } /* end switch */
  1184.  
  1185.    *p='\0';
  1186.    r->strlength = strlen(r->strptr);
  1187.    return(0);
  1188.  
  1189.    } /* End segetsopt */
  1190.  
  1191. /*-----------------------------------*/
  1192. /* GIVESOCKET (18) Unimplemented     */
  1193. /*-----------------------------------*/
  1194.  
  1195. /*-----------------------------------*/
  1196. /* INITIALIZE Function (19)          */
  1197. /*-----------------------------------*/
  1198. INT soinit( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1199.    PCH    p;
  1200.    INT    so;
  1201.    PRXSTRING arg3,arg4;
  1202.  
  1203.    if( RXNULLSTRING(*a) || RXZEROLENSTRING(*a) ||
  1204.        (a->strlength>8) ) {
  1205.       soerr( r, EINVALIDRXSOCKETCALL  );
  1206.       return(0);
  1207.      }
  1208.    strncpy(Subtaskid,a->strptr,8);
  1209.    *(Subtaskid+8)='\0';
  1210.  
  1211.    maxsockets = 40;
  1212.    if( n>2 ) {
  1213.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1214.       if( RXVALIDSTRING(*arg3) ) {
  1215.          if( string2long(arg3,&maxsockets)==FALSE ) {
  1216.             soerr( r, EINVALIDRXSOCKETCALL );
  1217.             return(0);
  1218.             }
  1219.          }
  1220.       if( maxsockets<=0 ) {
  1221.          soerr( r, EINVALIDRXSOCKETCALL );
  1222.          return(0);
  1223.          }
  1224.       } /* end n>2 */
  1225.  
  1226.    /*----------------------*/
  1227.    /* Alloc internal socket*/
  1228.    /* structure            */
  1229.    /*----------------------*/
  1230.    ps = (PSTAB)(malloc( maxsockets * sizeof(STAB) ));
  1231.  
  1232.  
  1233.    /* sock_init Not implemented for emx sockets  
  1234.     . s = sock_init(); 
  1235.     . if( s<0 ) {
  1236.     .    soerr( r, errno );
  1237.     .    return(0);
  1238.     .    }
  1239.     */
  1240.  
  1241.    p = r->strptr; 
  1242.    p += sprintf( p, "0 %s 40 TCPIP", a->strptr );
  1243.    r->strlength = strlen(r->strptr);
  1244.    return(0);
  1245.    } /* End soinit */
  1246.  
  1247. /*-----------------------------------*/
  1248. /* IOCTL Function (20)               */
  1249. /*-----------------------------------*/
  1250. INT soioctl( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1251.    PCH     p;
  1252.    INT     i;
  1253.    LONG    so;
  1254.    INT     how;
  1255.    INT     rc;
  1256.    PRXSTRING arg3,arg4;
  1257.    static PCH ioc[] = {
  1258.       "FIONBIO",        "FIONREAD",    
  1259.       "SIOCATMARK",        "SIOFIFADDR",
  1260.       "SIOCGIFBRDADDR",        "SIOCGIFCONF",    "SIOCGIFDSTADDR",
  1261.       "SIOCGIFFLAGS",        "SIOCGIFMETRIC","SIOCGIFNETMASK"
  1262.       "" };
  1263.    static INT iox[] = {
  1264.       FIONBIO,        FIONREAD,
  1265.       0,        0,
  1266.       0,        0,    0,
  1267.       0,        0,      0 };
  1268.  
  1269.    if( RXVALIDSTRING(*a) ) {
  1270.       if( string2long(a,&so)==FALSE ) {
  1271.          soerr( r, EINVALIDRXSOCKETCALL );
  1272.          return(0);
  1273.          }
  1274.       }
  1275.  
  1276.    /* Validate 'icmd' */
  1277.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1278.    if( !RXVALIDSTRING(*arg3) ) {
  1279.       soerr( r, EINVALIDRXSOCKETCALL );
  1280.       return(0);
  1281.       }
  1282.    for( i=0; *(ioc[i]); i++ ) {
  1283.       if( stricmp( ioc[i], arg3->strptr )==0 ) break;
  1284.       }
  1285.    if( !*(ioc[i]) ) {
  1286.       soerr( r, EINVALIDRXSOCKETCALL );
  1287.       return(0);
  1288.       }
  1289.    i = iox[i]; /* Get value for IOCTL */
  1290.    /*----------------------------*/
  1291.    /* There is no reason why the */
  1292.    /* SIOCGIF* commands can not  */
  1293.    /* work, except they are not  */
  1294.    /* implemented by the distrib-*/
  1295.    /* uted Rexx sockets package  */
  1296.    /*----------------------------*/
  1297.    if( i==0 ) {
  1298.       soerr( r, EINVALIDRXSOCKETCALL );
  1299.       return(0);
  1300.       }
  1301.  
  1302.    if( n>3 ) {
  1303.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1304.       if( RXVALIDSTRING(*arg4) ) {
  1305.          if( i!=FIONBIO ) {
  1306.             soerr( r, EINVALIDRXSOCKETCALL );
  1307.             return(0);
  1308.             }
  1309.          if( stricmp(arg4->strptr,"ON")==0 ) how=0;
  1310.          else if( stricmp(arg4->strptr,"OFF")==0 ) how=1;
  1311.          else {
  1312.             soerr( r, EINVALIDRXSOCKETCALL );
  1313.             return(0);
  1314.             }
  1315.          }
  1316.       } /* end n>3 */
  1317.  
  1318.    rc = ioctl( so, i, &how );
  1319.    if( rc<0 ) {
  1320.       soerr( r, errno );
  1321.       return(0);
  1322.       }
  1323.  
  1324.    p = r->strptr; 
  1325.    if( i!=FIONBIO ) 
  1326.       strcpy(p,"0");
  1327.    else p+= sprintf( p, "0 %d", how );
  1328.    r->strlength = strlen(r->strptr);
  1329.    return(0);
  1330.    } /* End soioctl */
  1331.  
  1332. /*-----------------------------------*/
  1333. /* LISTEN Function (21)              */
  1334. /*-----------------------------------*/
  1335. INT solisten( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1336.    PCH    p;
  1337.    LONG   s;
  1338.    LONG   backlog;
  1339.    INT    rc;
  1340.    PRXSTRING arg3;
  1341.  
  1342.    if( string2long(a,&s)==FALSE ) {
  1343.       soerr( r, EINVALIDRXSOCKETCALL );
  1344.       return(0);
  1345.       }
  1346.  
  1347.    backlog = 10;
  1348.    if( n>2 ) {
  1349.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1350.       if( RXVALIDSTRING(*arg3) ) {
  1351.          if( string2long(arg3,&backlog)==FALSE ) {
  1352.             soerr( r, EINVALIDRXSOCKETCALL );
  1353.             return(0);
  1354.             }
  1355.          }
  1356.       } /* end n>2 */
  1357.  
  1358.    if( (backlog<0) || (backlog>10) ) {
  1359.       soerr( r, EINVALIDRXSOCKETCALL );
  1360.       return(0);
  1361.       }
  1362.  
  1363.    rc = listen( s, backlog );
  1364.  
  1365.    if( rc ) {
  1366.       soerr( r, errno );
  1367.       return(0);
  1368.       }
  1369.  
  1370.    strcpy( r->strptr, "0" );
  1371.    r->strlength = strlen(r->strptr);
  1372.    return(0);
  1373.    } /* End solisten */
  1374.  
  1375. /*-----------------------------------*/
  1376. /* READ Function (22)                */
  1377. /*-----------------------------------*/
  1378. INT soread( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1379.    PCH    p;
  1380.    LONG   s;
  1381.    LONG   len=10000;
  1382.    INT    cnt;
  1383.    INT    rc;
  1384.    PRXSTRING arg3;
  1385.    PVOID  pMem;
  1386.    PCH    buf;
  1387.  
  1388.    if( string2long(a,&s)==FALSE ) {
  1389.       soerr( r, EINVALIDRXSOCKETCALL );
  1390.       return(0);
  1391.       }
  1392.  
  1393.    if( n>2 ) {
  1394.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1395.       if( !(RXVALIDSTRING(*arg3)) || (RXZEROLENSTRING(*arg3)) ) {
  1396.          soerr( r, EINVALIDRXSOCKETCALL  );
  1397.          return(0);
  1398.          }
  1399.       if( string2long(arg3,&len)==FALSE ) {
  1400.          soerr( r, EINVALIDRXSOCKETCALL );
  1401.          return(0);
  1402.          }
  1403.       } /* end n>2 */
  1404.  
  1405.    buf = malloc(len);
  1406.    if( buf==NULL ) {
  1407.       soerr( r, errno );
  1408.       return(0);
  1409.       }
  1410.    cnt = read( s, buf, len );
  1411.    if( cnt<=0 ) {
  1412.       soerr( r, errno );
  1413.       free(buf);
  1414.       return(0);
  1415.       }
  1416.    if( cnt>240 ) {  /* Need to get a new RXSTRING for result */
  1417.       rc= DosAllocMem( &pMem, cnt+16, 
  1418.                        PAG_COMMIT|PAG_READ|PAG_WRITE );
  1419.       if( rc ) {
  1420.          soerr( r, ENOMEM );
  1421.          free(buf);
  1422.          return(0);
  1423.          }
  1424.       r->strptr = pMem;
  1425.       }
  1426.  
  1427.    p = r->strptr;
  1428.    p += sprintf( p, "0 %d ", cnt );
  1429.    memcpy( p, buf, cnt );
  1430.    free(buf);
  1431.    p+=cnt;
  1432.    *p = '\0';
  1433.    r->strlength = p - r->strptr;
  1434.    return(0);
  1435.    } /* End soread */
  1436.  
  1437. /*-----------------------------------*/
  1438. /* RECV Function (23)                */
  1439. /*-----------------------------------*/
  1440. INT sorecv( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1441.    PCH    p;
  1442.    PRXSTRING arg3,arg4;
  1443.    LONG   s;
  1444.    LONG   len=10000; /* Defaults */
  1445.    INT    flags=0;
  1446.    INT    cnt;
  1447.    INT    rc;
  1448.    PVOID  pMem;
  1449.    PCH    buf;
  1450.    PCH    tmp;
  1451.  
  1452.    if( string2long(a,&s)==FALSE ) {
  1453.       soerr( r, EINVALIDRXSOCKETCALL );
  1454.       return(0);
  1455.       }
  1456.  
  1457.    if( n>2 ) {
  1458.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1459.       if( !(RXVALIDSTRING(*arg3)) || (RXZEROLENSTRING(*arg3)) ) {
  1460.          soerr( r, EINVALIDRXSOCKETCALL  );
  1461.          return(0);
  1462.          }
  1463.       if( string2long(arg3,&len)==FALSE ) {
  1464.          soerr( r, EINVALIDRXSOCKETCALL );
  1465.          return(0);
  1466.          }
  1467.       } /* end n>2 */
  1468.  
  1469.    if( n>3 ) {
  1470.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1471.       if( !(RXVALIDSTRING(*arg4)) ) {
  1472.          soerr( r, EINVALIDRXSOCKETCALL  );
  1473.          return(0);
  1474.          }
  1475.       if( !(RXZEROLENSTRING(*arg4)) ) {
  1476.          tmp = malloc(arg4->strlength+1); /* Make copy of argument */
  1477.          strncpy( tmp, arg4->strptr, arg4->strlength );
  1478.          *(tmp+arg4->strlength)='\0';
  1479.          p = strtok(tmp," ");
  1480.          while( p!=NULL ) {
  1481.             if( (stricmp(p,"MSG_OOB")==0) ||
  1482.                 (stricmp(p,"OOB")==0)     ||
  1483.                 (stricmp(p,"OUT_OF_BAND")==0) )
  1484.                  flags|=MSG_OOB;
  1485.             else if( (stricmp(p,"MSG_PEEK")==0) ||
  1486.                      (stricmp(p,"PEEK")==0) )
  1487.                  flags|=MSG_PEEK;
  1488.             else {
  1489.                soerr( r, EINVALIDRXSOCKETCALL );
  1490.                free(tmp);
  1491.                return(0);
  1492.                }
  1493.             p=strtok( NULL, " " );
  1494.             }
  1495.          free(tmp);
  1496.          }
  1497.       } /* end n>3 */
  1498.  
  1499.    buf = malloc(len);
  1500.    if( buf==NULL ) {
  1501.       soerr( r, errno );
  1502.       return(0);
  1503.       }
  1504.  
  1505.    cnt = recv( s, buf, len, flags );
  1506.  
  1507.    if( cnt<=0 ) {
  1508.       soerr( r, errno );
  1509.       free(buf);
  1510.       return(0);
  1511.       }
  1512.    if( cnt>240 ) {  /* Need to get a new RXSTRING for result */
  1513.       rc= DosAllocMem( &pMem, cnt+16, 
  1514.                        PAG_COMMIT|PAG_READ|PAG_WRITE );
  1515.       if( rc ) {
  1516.          soerr( r, ENOMEM );
  1517.          free(buf);
  1518.          return(0);
  1519.          }
  1520.       r->strptr = pMem;
  1521.       }
  1522.  
  1523.    p = r->strptr;
  1524.    p += sprintf( p, "0 %d ", cnt );
  1525.    memcpy( p, buf, cnt );
  1526.    free(buf);
  1527.    p+=cnt;
  1528.    *p = '\0';
  1529.    r->strlength = p - r->strptr;
  1530.    return(0);
  1531.    } /* End sorecv */
  1532.  
  1533. /*-----------------------------------*/
  1534. /* RECVFROM Function (24)            */
  1535. /*-----------------------------------*/
  1536. INT sorecvfr( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1537.    PCH    p;
  1538.    PRXSTRING arg3,arg4;
  1539.    LONG   s;
  1540.    LONG   len=10000; /* Defaults */
  1541.    INT    flags=0;
  1542.    INT    cnt;
  1543.    INT    rc;
  1544.    PVOID  pMem;
  1545.    PCH    buf;
  1546.    PCH    tmp;
  1547.    struct sockaddr_in addr;
  1548.    INT    addrl;
  1549.  
  1550.    if( string2long(a,&s)==FALSE ) {
  1551.       soerr( r, EINVALIDRXSOCKETCALL );
  1552.       return(0);
  1553.       }
  1554.  
  1555.    if( n>2 ) {
  1556.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1557.       if( !(RXVALIDSTRING(*arg3)) || (RXZEROLENSTRING(*arg3)) ) {
  1558.          soerr( r, EINVALIDRXSOCKETCALL  );
  1559.          return(0);
  1560.          }
  1561.       if( string2long(arg3,&len)==FALSE ) {
  1562.          soerr( r, EINVALIDRXSOCKETCALL );
  1563.          return(0);
  1564.          }
  1565.       } /* end n>2 */
  1566.  
  1567.    if( n>3 ) {
  1568.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1569.       if( !(RXVALIDSTRING(*arg4)) ) {
  1570.          soerr( r, EINVALIDRXSOCKETCALL  );
  1571.          return(0);
  1572.          }
  1573.       if( !(RXZEROLENSTRING(*arg4)) ) {
  1574.          tmp = malloc(arg4->strlength+1); /* Make copy of argument */
  1575.          strncpy( tmp, arg4->strptr, arg4->strlength );
  1576.          *(tmp+arg4->strlength)='\0';
  1577.          p = strtok(tmp," ");
  1578.          while( p!=NULL ) {
  1579.             if( (stricmp(p,"MSG_OOB")==0) ||
  1580.                 (stricmp(p,"OOB")==0)     ||
  1581.                 (stricmp(p,"OUT_OF_BAND")==0) )
  1582.                  flags|=MSG_OOB;
  1583.             else if( (stricmp(p,"MSG_PEEK")==0) ||
  1584.                      (stricmp(p,"PEEK")==0) )
  1585.                  flags|=MSG_PEEK;
  1586.             else {
  1587.                soerr( r, EINVALIDRXSOCKETCALL );
  1588.                free(tmp);
  1589.                return(0);
  1590.                }
  1591.             p=strtok( NULL, " " );
  1592.             }
  1593.          free(tmp);
  1594.          }
  1595.       } /* end n>3 */
  1596.  
  1597.    buf = malloc(len);
  1598.    if( buf==NULL ) {
  1599.       soerr( r, errno );
  1600.       return(0);
  1601.       }
  1602.  
  1603.    addrl = sizeof(addr);
  1604.    cnt = recvfrom( s, buf, len, flags, (struct sockaddr *)&addr, &addrl );
  1605.  
  1606.    if( cnt<=0 ) {
  1607.       soerr( r, errno );
  1608.       free(buf);
  1609.       return(0);
  1610.       }
  1611.    if( cnt>240 ) {  /* Need to get a new RXSTRING for result */
  1612.       rc= DosAllocMem( &pMem, cnt+16, 
  1613.                        PAG_COMMIT|PAG_READ|PAG_WRITE );
  1614.       if( rc ) {
  1615.          soerr( r, ENOMEM );
  1616.          free(buf);
  1617.          return(0);
  1618.          }
  1619.       r->strptr = pMem;
  1620.       }
  1621.  
  1622.    p = r->strptr;
  1623.    p += sprintf( p, "0 %d ", cnt );
  1624.    if( addr.sin_family>=AF_MAX )
  1625.       addr.sin_family=AF_UNSPEC;
  1626.    strcat(p,fam[addr.sin_family]);
  1627.    p += strlen(p);
  1628.    if( addr.sin_family==AF_INET ) {
  1629.       p += sprintf( p, " %d %s ", ntohs(addr.sin_port),
  1630.                    inet_ntoa(addr.sin_addr) );
  1631.       } /* End INET */
  1632.    memcpy( p, buf, cnt );
  1633.    free(buf);
  1634.    p+=cnt;
  1635.    *p = '\0';
  1636.    r->strlength = p - r->strptr;
  1637.    return(0);
  1638.    } /* End sorecvfr */
  1639.  
  1640. /*-----------------------------------*/
  1641. /* RESOLVE Function (25)             */
  1642. /*-----------------------------------*/
  1643. INT soresolv( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1644.    PCH    p;
  1645.    LONG   timeout=-1;
  1646.    INT    rc;
  1647.    PRXSTRING arg3;
  1648.    struct in_addr host_addr;
  1649.    struct hostent *pHE;
  1650.  
  1651.    if( !RXVALIDSTRING(*a) ) {
  1652.       soerr( r, EINVALIDRXSOCKETCALL );
  1653.       return(0);
  1654.       }
  1655.  
  1656.    /* Get 'timeout' if provided */
  1657.    if( n>2) {
  1658.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1659.       if( RXVALIDSTRING(*arg3) ) {
  1660.          if( string2long(arg3,&timeout)==FALSE ) {
  1661.             soerr( r, EINVALIDRXSOCKETCALL );
  1662.             return(0);
  1663.             }
  1664.          if( timeout<=0 ) {
  1665.             soerr( r, EINVALIDRXSOCKETCALL );
  1666.             return(0);
  1667.             }
  1668.          }
  1669.       } /* end n>2 */
  1670.  
  1671.    p = r->strptr;
  1672.    /* Do we have an IP address or a host/domain name? */
  1673.    if( isalpha(*(a->strptr)) ) { /* Host name */
  1674.       pHE = gethostbyname( a->strptr );
  1675.       if( pHE==NULL ) {
  1676.          soerr( r, h_errno );
  1677.          return(0);
  1678.          }
  1679.       memcpy( &host_addr.s_addr, pHE->h_addr, sizeof host_addr.s_addr );
  1680.       p+= sprintf( p, "0 %s %s", inet_ntoa(host_addr), pHE->h_name );
  1681.       }
  1682.    else {  /* IP address */
  1683.       host_addr.s_addr = inet_addr(a->strptr);
  1684.       pHE = gethostbyaddr( (PCH)&host_addr, sizeof(struct in_addr) , AF_INET );
  1685.       if( pHE==NULL ) {
  1686.          soerr( r, h_errno );
  1687.          return(0);
  1688.          }
  1689.       p+= sprintf( p, "0 %s %s", a->strptr, pHE->h_name );
  1690.       }
  1691.  
  1692.    *p='\0';
  1693.    r->strlength = strlen(r->strptr);
  1694.    return(0);
  1695.    } /* End soresolv */
  1696.  
  1697. /*-----------------------------------*/
  1698. /* SELECT Function (26)              */
  1699. /*-----------------------------------*/
  1700. INT sosel( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1701.    PCH    p;
  1702.    INT    rc;
  1703.    INT    nsock=0;
  1704.    PRXSTRING arg3;
  1705.    struct timeval tv, *ptv;
  1706.    fd_set rset,wset,xset;
  1707.    fd_set *prset,*pwset,*pxset,*pt;
  1708.    PCH    tmp;
  1709.  
  1710.    ptv = (struct timeval *)NULL; /* Default - no timeout */
  1711.    prset = (fd_set *)NULL;
  1712.    pwset = (fd_set *)NULL;
  1713.    pxset = (fd_set *)NULL;
  1714.    FD_ZERO(&rset);                /* Clear all fd sets    */
  1715.    FD_ZERO(&wset);
  1716.    FD_ZERO(&xset);
  1717.  
  1718.    /* get socket mask if present */
  1719.    pt = (fd_set *)NULL;
  1720.    if( n>1 ) {
  1721.       if( !(RXVALIDSTRING(*a)) ) {
  1722.          soerr( r, EINVALIDRXSOCKETCALL  );
  1723.          return(0);
  1724.          }
  1725.       if( !(RXZEROLENSTRING(*a)) ) {
  1726.          tmp = malloc(a->strlength+1); /* Make copy of argument */
  1727.          strncpy( tmp, a->strptr, a->strlength );
  1728.          *(tmp+a->strlength)='\0';
  1729.          p = strtok(tmp," ");
  1730.          while( p!=NULL ) {
  1731.             if( (stricmp(p,"READ")==0 ) )           pt = (fd_set *)&rset;
  1732.             else if( (stricmp(p,"WRITE")==0 ) )     pt = (fd_set *)&wset;
  1733.             else if( (stricmp(p,"EXCEPTION")==0 ) ) pt = (fd_set *)&xset;
  1734.             else if( !isdigit(*p) ) {
  1735.                soerr( r, EINVALIDRXSOCKETCALL );
  1736.                free(tmp);
  1737.                return(0);
  1738.                }
  1739.             if( pt==(fd_set *)NULL ) {
  1740.                soerr( r, EINVALIDRXSOCKETCALL );
  1741.                free(tmp);
  1742.                return(0);
  1743.                }
  1744.             rc = getint(p,strlen(p));
  1745.             if( rc<0 || rc>FD_SETSIZE ) {
  1746.                soerr( r, EINVALIDRXSOCKETCALL );
  1747.                free(tmp);
  1748.                return(0);
  1749.                }
  1750.             FD_SET(rc,pt);
  1751.             p=strtok( NULL, " " );
  1752.             } /* end while */
  1753.          free(tmp);
  1754.          } /* end !RXZEROLENSTRING */
  1755.       } /* end n>1 */
  1756.  
  1757.    /* get timeout if present */
  1758.    if( n>2) {
  1759.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1760.       if( RXNULLSTRING(*arg3) || RXZEROLENSTRING(*arg3) ) /* continue */ ;
  1761.       else { /* Parse Timeout */
  1762.          if( stricmp( arg3->strptr, "FOREVER" )==0 ) /* continue */ ; 
  1763.          else if( strnicmp( arg3->strptr, "SIGNAL", 6 )==0 ) { 
  1764.             soerr( r, errno ); /* Not supported */
  1765.             return(0);
  1766.             }
  1767.          else if( isdigit( *(arg3->strptr)) ) {
  1768.             /* get time */
  1769.             ptv = &tv;
  1770.             }
  1771.          else {
  1772.             soerr( r, errno );
  1773.             return(0);
  1774.             }
  1775.          }
  1776.       } /* end n>2 */
  1777.  
  1778.    rc = select( nsock, prset, pwset, pxset, ptv );
  1779.  
  1780.    if( rc<0 ) {  /* Error */
  1781.       soerr( r, errno );
  1782.       return(0);
  1783.       }
  1784.    /* NOTE: I have timeout returning RC=0 with  */
  1785.    /*       number of sockets=0, is this right? */
  1786.    if( rc==0 ) { /* Timeout */
  1787.       strcpy( r->strptr, "0 0" );
  1788.       r->strlength = strlen(r->strptr);
  1789.       return(0);
  1790.       }
  1791.  
  1792.    *p='\0';
  1793.    r->strlength = strlen(r->strptr);
  1794.    return(0);
  1795.    } /* End sosel */
  1796.  
  1797. /*-----------------------------------*/
  1798. /* SEND Function (27)                */
  1799. /*-----------------------------------*/
  1800. INT sosend( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1801.    PCH    p;
  1802.    PRXSTRING arg3,arg4;
  1803.    LONG   s;
  1804.    INT    flags=0;
  1805.    INT    rc;
  1806.    PCH    tmp;
  1807.  
  1808.    if( string2long(a,&s)==FALSE ) {
  1809.       soerr( r, EINVALIDRXSOCKETCALL );
  1810.       return(0);
  1811.       }
  1812.  
  1813.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1814.    if( !(RXVALIDSTRING(*arg3)) || (RXZEROLENSTRING(*arg3)) ) {
  1815.       soerr( r, EINVALIDRXSOCKETCALL  );
  1816.       return(0);
  1817.       }
  1818.  
  1819.    if( n>3 ) {
  1820.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1821.       if( !(RXVALIDSTRING(*arg4)) ) {
  1822.          soerr( r, EINVALIDRXSOCKETCALL  );
  1823.          return(0);
  1824.          }
  1825.       if( !(RXZEROLENSTRING(*arg4)) ) {
  1826.          tmp = malloc(arg4->strlength+1); /* Make copy of argument */
  1827.          strncpy( tmp, arg4->strptr, arg4->strlength );
  1828.          *(tmp+arg4->strlength)='\0';
  1829.          p = strtok(tmp," ");
  1830.          while( p!=NULL ) {
  1831.             if( (stricmp(p,"MSG_OOB")==0) ||
  1832.                 (stricmp(p,"OOB")==0)     ||
  1833.                 (stricmp(p,"OUT_OF_BAND")==0) )
  1834.                  flags|=MSG_OOB;
  1835.             else if( (stricmp(p,"MSG_PEEK")==0) ||
  1836.                      (stricmp(p,"PEEK")==0) )
  1837.                  flags|=MSG_PEEK;
  1838.             else {
  1839.                soerr( r, EINVALIDRXSOCKETCALL );
  1840.                free(tmp);
  1841.                return(0);
  1842.                }
  1843.             p=strtok( NULL, " " );
  1844.             }
  1845.          free(tmp);
  1846.          }
  1847.       } /* end n>3 */
  1848.  
  1849.    rc = send( s, arg3->strptr, arg3->strlength, flags );
  1850.  
  1851.    if( rc<0 ) {
  1852.       soerr( r, errno );
  1853.       return(0);
  1854.       }
  1855.  
  1856.    p = r->strptr;
  1857.    p += sprintf( p, "0 %d", arg3->strlength );
  1858.    *p = '\0';
  1859.    r->strlength = strlen(r->strptr);
  1860.    return(0);
  1861.    } /* End sosend */
  1862.  
  1863. /*-----------------------------------*/
  1864. /* SENDTO Function (28)              */
  1865. /*-----------------------------------*/
  1866. INT sosendto( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1867.    PCH    p;
  1868.    PRXSTRING arg3,arg4,arg5;
  1869.    LONG   s;
  1870.    INT    flags=0;
  1871.    INT    rc;
  1872.    INT    cnt;
  1873.    PCH    tmp;
  1874.    struct sockaddr_in addr, *paddr;
  1875.    INT    addrl;
  1876.  
  1877.    if( string2long(a,&s)==FALSE ) {
  1878.       soerr( r, EINVALIDRXSOCKETCALL );
  1879.       return(0);
  1880.       }
  1881.  
  1882.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1883.    if( !(RXVALIDSTRING(*arg3)) || (RXZEROLENSTRING(*arg3)) ) {
  1884.       soerr( r, EINVALIDRXSOCKETCALL  );
  1885.       return(0);
  1886.       }
  1887.  
  1888.    if( n>3 ) {
  1889.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1890.       if( !(RXVALIDSTRING(*arg4)) ) {
  1891.          soerr( r, EINVALIDRXSOCKETCALL  );
  1892.          return(0);
  1893.          }
  1894.       if( !(RXZEROLENSTRING(*arg4)) ) {
  1895.          tmp = malloc(arg4->strlength+1); /* Make copy of argument */
  1896.          strncpy( tmp, arg4->strptr, arg4->strlength );
  1897.          *(tmp+arg4->strlength)='\0';
  1898.          p = strtok(tmp," ");
  1899.          while( p!=NULL ) {
  1900.             if( (stricmp(p,"MSG_OOB")==0) ||
  1901.                 (stricmp(p,"OOB")==0)     ||
  1902.                 (stricmp(p,"OUT_OF_BAND")==0) )
  1903.                  flags|=MSG_OOB;
  1904.             else if( (stricmp(p,"MSG_PEEK")==0) ||
  1905.                      (stricmp(p,"PEEK")==0) )
  1906.                  flags|=MSG_PEEK;
  1907.             else {
  1908.                soerr( r, EINVALIDRXSOCKETCALL );
  1909.                free(tmp);
  1910.                return(0);
  1911.                }
  1912.             p=strtok( NULL, " " );
  1913.             } /* end while */
  1914.          free(tmp);
  1915.          } /* end !RXZEROLENSTRING */
  1916.       } /* end n>3 */
  1917.  
  1918.    paddr = NULL;
  1919.  
  1920.    if( n>4 ) {
  1921.       arg5 = (PRXSTRING)( (PUCHAR)arg4 + sizeof(RXSTRING) );
  1922.       if( RXVALIDSTRING(*arg5) && !RXZEROLENSTRING(*arg5) ) {
  1923.          paddr = &addr;
  1924.          addrl = sizeof(addr);
  1925.          if( parseaddress(arg5,paddr)==FALSE ) {
  1926.             soerr( r, EINVALIDRXSOCKETCALL  );
  1927.             return(0);
  1928.             }
  1929.          } /* end RXVALIDSTRING */
  1930.       } /* end n>4 */
  1931.  
  1932.    if( paddr==NULL ) {
  1933.       cnt = send( s, arg3->strptr, arg3->strlength, flags );
  1934.       if( cnt>=0 ) cnt=arg3->strlength;
  1935.       }
  1936.    else {
  1937.       cnt = sendto( s, arg3->strptr, arg3->strlength, flags, (struct sockaddr *)&addr, addrl );
  1938.       }
  1939.  
  1940.    if( cnt<=0 ) {
  1941.       soerr( r, errno );
  1942.       return(0);
  1943.       }
  1944.  
  1945.    p = r->strptr;
  1946.    p += sprintf( p, "0 %d", cnt );
  1947.    *p = '\0';
  1948.    r->strlength = p - r->strptr;
  1949.    return(0);
  1950.    } /* End sosendto */
  1951.  
  1952. /*-----------------------------------*/
  1953. /* SETSOCKOPT Function (29)          */
  1954. /*-----------------------------------*/
  1955. INT sosetsopt( ULONG n, PRXSTRING a, PRXSTRING r ) {
  1956.    PCH    p;
  1957.    LONG   s; 
  1958.    LONG   optval;
  1959.    INT    rc;
  1960.    INT    i,j;
  1961.    PSTAB  pst;
  1962.    PRXSTRING arg3,arg4,arg5;
  1963.    char   optbuf[80]; /* Max size buffer */
  1964.    INT    optlen;
  1965.    typedef INT  *POPTINT;
  1966.    typedef LONG *POPTLONG;
  1967.    typedef struct linger *PLINGER;
  1968.  
  1969.    if( string2long(a,&s)==FALSE ) {
  1970.       soerr( r, EINVALIDRXSOCKETCALL );
  1971.       return(0);
  1972.       }
  1973.  
  1974.    /*----------------------*/
  1975.    /* Validate Level       */
  1976.    /*----------------------*/
  1977.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  1978.    if( RXNULLSTRING(*arg3) || RXZEROLENSTRING(*arg3) ) {
  1979.       soerr( r, EINVALIDRXSOCKETCALL );
  1980.       return(0);
  1981.       }
  1982.    if( stricmp( arg3->strptr, "SOL_SOCKET" )!=0 ) { 
  1983.       soerr( r, EINVALIDRXSOCKETCALL );
  1984.       return(0);
  1985.       }
  1986.    /*----------------------*/
  1987.    /* Validate Option      */
  1988.    /*----------------------*/
  1989.    arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  1990.    if( RXNULLSTRING(*arg4) || RXZEROLENSTRING(*arg4) ) {
  1991.       soerr( r, EINVALIDRXSOCKETCALL  );
  1992.       return(0);
  1993.       }
  1994.    for( i=0; i<OPT_MAX; i++ ) {
  1995.       if( stricmp( arg4->strptr, opt[i] )==0 ) break;
  1996.       }
  1997.    if( i>=OPT_MAX ) {
  1998.       soerr( r, EINVALIDRXSOCKETCALL );
  1999.       return(0);
  2000.       }
  2001.    i = optx[i];
  2002.  
  2003.    /*----------------------*/
  2004.    /* Validate Value       */
  2005.    /*----------------------*/
  2006.    arg5 = (PRXSTRING)( (PUCHAR)arg4 + sizeof(RXSTRING) );
  2007.    if( RXNULLSTRING(*arg5) || RXZEROLENSTRING(*arg5) ) {
  2008.       soerr( r, EINVALIDRXSOCKETCALL  );
  2009.       return(0);
  2010.       }
  2011.    if( stricmp( arg5->strptr, "ON" )==0 )       optval=1;
  2012.    else if( stricmp( arg5->strptr, "OFF" )==0 ) optval=0;
  2013.    else { 
  2014.          if( string2long(a,&optval)==FALSE ) {
  2015.             soerr( r, EINVALIDRXSOCKETCALL );
  2016.             return(0);
  2017.             }
  2018.          if( optval!=0 ) optval=1;
  2019.          }
  2020.  
  2021.    /*----------------------*/
  2022.    /* Find Socket          */
  2023.    /*----------------------*/
  2024.    pst = ps;
  2025.    for( j=1; j<=nsock; j++ ) {
  2026.       if( pst->stab_snum==s ) break;
  2027.       pst = (PSTAB)( (PUCHAR)pst + sizeof(STAB) );
  2028.       }
  2029.    if( j>nsock ) {
  2030.       soerr( r, EINVALIDRXSOCKETCALL  );
  2031.       return(0);
  2032.       }
  2033.  
  2034.    /*----------------------*/
  2035.    /* ASCII and EBCDIC are */
  2036.    /* Internal options     */
  2037.    /* Translation table is */
  2038.    /* always "STANDARD"    */
  2039.    /*----------------------*/
  2040.    switch( i ) {
  2041.       case SO_ASCII:
  2042.          pst->stab_satt = optval? 0:1;
  2043.          p = r->strptr;
  2044.          strcpy( p, "0" ); 
  2045.          p += strlen(p);
  2046.          r->strlength = strlen(r->strptr);
  2047.          return(0);
  2048.       case SO_EBCDIC:
  2049.          pst->stab_satt = optval? 1:0;
  2050.          p = r->strptr;
  2051.          strcpy( p, "0" ); 
  2052.          p += strlen(p);
  2053.          r->strlength = strlen(r->strptr);
  2054.          return(0);
  2055.       default: break; 
  2056.       } /* end switch */
  2057.    switch( i ) {
  2058.       case SO_BROADCAST:
  2059.       case SO_DEBUG:
  2060.       case SO_DONTROUTE:
  2061.       case SO_KEEPALIVE:
  2062.       case SO_OOBINLINE:
  2063.       case SO_REUSEADDR:
  2064.          p+= sprintf( p, "%s",optbuf[0]? "On": "Off");
  2065.          break;
  2066.       case SO_ERROR:
  2067.       case SO_TYPE:
  2068.       case SO_USELOOPBACK:
  2069.       case SO_RCVLOWAT:
  2070.       case SO_RCVTIMEO:
  2071.       case SO_SNDLOWAT:
  2072.       case SO_SNDTIMEO:
  2073.          p+= sprintf( p, "%d", (POPTINT)&optbuf);
  2074.          break;
  2075.       case SO_RCVBUF:
  2076.       case SO_SNDBUF:
  2077.          p+= sprintf( p, "%ld", (POPTLONG)&optbuf);
  2078.          break;
  2079.       case SO_LINGER:
  2080.          p+= sprintf( p, "%s %d", ((PLINGER)&optbuf)->l_onoff? "Off": "On",
  2081.                       ((PLINGER)&optbuf)->l_linger);
  2082.          break;
  2083.       } /* end switch */
  2084.  
  2085.  
  2086.    optlen = sizeof optbuf;
  2087.  
  2088.    rc = setsockopt( s, SOL_SOCKET, i, (PUCHAR)&optbuf, optlen );
  2089.  
  2090.    if( rc ) {
  2091.       soerr( r, errno );
  2092.       return(0);
  2093.       }
  2094.  
  2095.    strcpy( r->strptr, "0" ); 
  2096.    r->strlength = strlen(r->strptr);
  2097.    return(0);
  2098.  
  2099.    } /* end sosetsopt */
  2100.  
  2101. /*-----------------------------------*/
  2102. /* SHUTDOWN Function (30)            */
  2103. /*-----------------------------------*/
  2104. INT soshut( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2105.    LONG   so;
  2106.    INT    rc;
  2107.    INT    how=2; /* Default='BOTH' */
  2108.    PRXSTRING arg3;
  2109.  
  2110.    if( string2long(a,&so)==FALSE ) {
  2111.       soerr( r, EINVALIDRXSOCKETCALL  );
  2112.       return(0);
  2113.       }
  2114.  
  2115.    if( n>2 ) {
  2116.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  2117.       if( RXVALIDSTRING(*arg3) ) { 
  2118.          if ( stricmp(arg3->strptr,"BOTH")==0 ) 
  2119.             how=2;
  2120.          else if( (stricmp(arg3->strptr,"FROM")==0)      ||
  2121.                   (stricmp(arg3->strptr,"RECEIVE")==0)   ||
  2122.                   (stricmp(arg3->strptr,"RECEIVING")==0) ||
  2123.                   (stricmp(arg3->strptr,"READ")==0) ||
  2124.                   (stricmp(arg3->strptr,"READING")==0) )
  2125.             how=0;
  2126.          else if( (stricmp(arg3->strptr,"TO")==0)        ||
  2127.                   (stricmp(arg3->strptr,"SEND")==0)      ||
  2128.                   (stricmp(arg3->strptr,"SENDING")==0)   ||
  2129.                   (stricmp(arg3->strptr,"WRITE")==0)     ||
  2130.                   (stricmp(arg3->strptr,"WRITING")==0) )
  2131.             how=1;
  2132.          else {
  2133.             soerr( r, EINVALIDRXSOCKETCALL  );
  2134.             return(0);
  2135.             }
  2136.          }
  2137.       } /* end n>2 */
  2138.  
  2139.    rc = shutdown( so, how );
  2140.  
  2141.    if( rc ) {
  2142.       soerr( r, errno );
  2143.       return(0);
  2144.       }
  2145.  
  2146.    strcpy( r->strptr, "0" ); 
  2147.    r->strlength = strlen(r->strptr);
  2148.    return(0);
  2149.  
  2150.    } /* end soshut */
  2151.  
  2152. /*-----------------------------------*/
  2153. /* SOCKET Function (31)              */
  2154. /*-----------------------------------*/
  2155. INT sosocket( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2156.    INT    domain   = AF_INET;     /* Defaults */
  2157.    INT    type     = SOCK_STREAM;
  2158.    INT    protocol = IPPROTO_TCP;
  2159.    INT    so;
  2160.    PCH    p;
  2161.    LONG   i;
  2162.    PRXSTRING arg3,arg4;
  2163.    PSTAB  pst;
  2164.  
  2165.    /* Look for 'AF_INET' or '2' */
  2166.    if( n>1 ) {
  2167.       if( RXVALIDSTRING(*a) ) {
  2168.          if( stricmp(a->strptr,"AF_INET")!=0 ) {
  2169.            if( string2long(a,&i)==FALSE ) {
  2170.           soerr( r, EINVALIDRXSOCKETCALL  );
  2171.           return(0);
  2172.               }
  2173.            if( i!=2 ) {
  2174.           soerr( r, EINVALIDRXSOCKETCALL  );
  2175.           return(0);
  2176.               }
  2177.             } /* End stricmp */
  2178.          } /* End RXVALIDSTRING */
  2179.       } /* End n>1 */
  2180.  
  2181.    /* Check 'type' argument */
  2182.    if( n>2 ) {
  2183.       arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  2184.       if( RXVALIDSTRING(*arg3) ) {
  2185.          for( i=0; i<TYPE_MAX; i++ ) {
  2186.             if( stricmp( typ[i], arg3->strptr )!=0 ) break;
  2187.             }
  2188.          if( i>=TYPE_MAX ) {      /* Invalid type       */
  2189.             soerr( r, EINVALIDRXSOCKETCALL );
  2190.             return(0);
  2191.             }
  2192.          type = i;
  2193.          if( type==TYPE_MAX-1 )  type--;; 
  2194.          type = i;
  2195.          /* Set up defaults for prptocol */
  2196.          if( type==SOCK_RAW )    protocol=0;
  2197.          if( type==SOCK_STREAM ) protocol=IPPROTO_TCP;
  2198.          if( type==SOCK_DGRAM )  protocol=IPPROTO_UDP;
  2199.          } /* End RXVALIDSTRING */
  2200.       } /* End n>2 */
  2201.  
  2202.    if( n>3 ) {
  2203.       arg4 = (PRXSTRING)( (PUCHAR)arg3 + sizeof(RXSTRING) );
  2204.       if( RXVALIDSTRING(*arg4) ) {
  2205.          if( arg4->strlength==11 ) {
  2206.             if ( stricmp(arg4->strptr,"IPPROTO_TCP")==0 ) 
  2207.                protocol=IPPROTO_TCP;
  2208.             else if( stricmp(arg4->strptr,"IPPROTO_UDP")==0 ) 
  2209.                protocol=IPPROTO_UDP;
  2210.             else if( stricmp(arg4->strptr,"IPPROTO_RAW")==0 ) 
  2211.                protocol=IPPROTO_RAW;
  2212.             else protocol=-1; /* (error) */
  2213.             } /* End length=11 */
  2214.          else if( arg4->strlength==12 ) {
  2215.             if ( stricmp(arg4->strptr,"IPPROTO_ICMP")==0 ) 
  2216.                protocol=IPPROTO_ICMP;
  2217.             else protocol=-1; /* (error) */
  2218.             } /* End length=12 */
  2219.          else if( arg4->strlength==3 ) {
  2220.             if ( stricmp(arg4->strptr,"RAW")==0 ) 
  2221.                protocol=IPPROTO_RAW;
  2222.             else protocol=-1; /* (error) */
  2223.             } /* End length=3 */
  2224.          else protocol=-1;
  2225.          if( protocol==-1 ) {
  2226.             soerr( r, EINVALIDRXSOCKETCALL  );
  2227.             return(0);
  2228.             }
  2229.          } /* End RXVALIDSTRING */
  2230.       } /* End n>3 */
  2231.  
  2232.    if( nsock>=maxsockets ) {
  2233.       soerr( r, EMAXSOCKETSREACHED );
  2234.       return(0);
  2235.       }
  2236.  
  2237.    so = socket( domain, type, protocol );
  2238.    pst = (PSTAB)( (PUCHAR)ps + (sizeof(STAB)*(nsock)) );
  2239.    nsock++;
  2240.    pst->stab_snum = so;
  2241.    pst->stab_satt = 0;
  2242.    
  2243.    p = r->strptr; 
  2244.    if( so<0 ) {
  2245.       p += sprintf( p, "%d",errno );
  2246.       strcpy(p,strerror(errno));
  2247.       }
  2248.    else {
  2249.       p += sprintf( p, "0 %d",so );
  2250.       *p='\0';
  2251.       }
  2252.    r->strlength = strlen(r->strptr);
  2253.    return(0);
  2254.    } /* End sosocket */
  2255.  
  2256. /*-----------------------------------*/
  2257. /* SOCKETSET Function (32)           */
  2258. /*-----------------------------------*/
  2259. INT soset( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2260.    PCH    p;
  2261.  
  2262.    if( maxsockets<=0 ) {
  2263.       soerr( r, ESUBTASKNOTACTIVE );
  2264.       return(0);
  2265.       }
  2266.  
  2267.    if( n>1 ) {
  2268.       if( RXVALIDSTRING(*a) ) {
  2269.          if( strcmp(Subtaskid,a->strptr)!=0 ) {
  2270.             soerr( r, ESUBTASKNOTACTIVE );
  2271.             return(0);
  2272.             }
  2273.          } /* Otherwise use current subtask */
  2274.      } /* end n>1 */
  2275.  
  2276.    p = r->strptr; 
  2277.    p += sprintf( p, "0 %s", Subtaskid );
  2278.    *p='\0';
  2279.    r->strlength = strlen(r->strptr);
  2280.    return(0);
  2281.    } /* end soset */
  2282.  
  2283. /*-----------------------------------*/
  2284. /* SOCKETSETLIST Function (33)       */
  2285. /*-----------------------------------*/
  2286. INT sossl( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2287.  
  2288.    if( maxsockets<=0 ) {
  2289.       soerr( r, ESUBTASKNOTACTIVE );
  2290.       return(0);
  2291.      }
  2292.  
  2293.    sprintf( r->strptr, "0 %s", Subtaskid );
  2294.    r->strlength = strlen(r->strptr);
  2295.    return(0);
  2296.    } /* end sossl */
  2297.  
  2298. /*-----------------------------------*/
  2299. /* SOCKETSETSTATUS Function (34)     */
  2300. /*-----------------------------------*/
  2301. INT sosss( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2302.    PCH    p;
  2303.  
  2304.    if( maxsockets<=0 ) {
  2305.       soerr( r, ESUBTASKNOTACTIVE );
  2306.       return(0);
  2307.  
  2308.    if( n>1 )
  2309.       if( RXVALIDSTRING(*a) ) {
  2310.          if( strcmp(Subtaskid,a->strptr)!=0 ) {
  2311.            soerr( r, ESUBTASKNOTACTIVE );
  2312.            return(0);
  2313.            }
  2314.         } /* Otherwise use current subtask */
  2315.      } /* end n>1 */
  2316.  
  2317.    /* Always 'Connected'? */
  2318.    p = r->strptr; 
  2319.    p += sprintf( p, "0 %s Connected Free %d Used %d", Subtaskid,
  2320.                     maxsockets-nsock, nsock );
  2321.    *p='\0';
  2322.    r->strlength = strlen(r->strptr);
  2323.    return(0);
  2324.    } /* end sosss */
  2325.  
  2326. /*-----------------------------------*/
  2327. /* TAKESOCKET (35) Unimplemented     */
  2328. /*-----------------------------------*/
  2329.  
  2330. /*-----------------------------------*/
  2331. /* TERMINATE Function (36)           */
  2332. /*-----------------------------------*/
  2333. INT soterm( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2334.  
  2335.    if( n>1 ) {
  2336.       if( RXVALIDSTRING(*a) ) {
  2337.         if( RXNULLSTRING(*a) || RXZEROLENSTRING(*a) ||
  2338.             (a->strlength>8) ) {
  2339.            soerr( r, EINVALIDRXSOCKETCALL  );
  2340.            return(0);
  2341.           }
  2342.         if( strcmp(Subtaskid,a->strptr)!=0 ) {
  2343.            soerr( r, ESUBTASKNOTACTIVE );
  2344.            return(0);
  2345.           }
  2346.         } /* Otherwise terminate current subtask */
  2347.      } /* end n>1 */
  2348.  
  2349.    CloseAllSockets();
  2350.  
  2351.    *(Subtaskid)='\0';
  2352.    sprintf( r->strptr, "0" );
  2353.    r->strlength = strlen(r->strptr);
  2354.    return(0);
  2355.    } /* end soterm */
  2356.  
  2357. /*-----------------------------------*/
  2358. /* TRACE (37) Unimplemented          */
  2359. /*-----------------------------------*/
  2360.  
  2361. /*-----------------------------------*/
  2362. /* TRANSLATE Function (38)           */
  2363. /*-----------------------------------*/
  2364. INT sotrans( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2365.    PCH       p;
  2366.    PRXSTRING arg3;
  2367.    INT       cnt;
  2368.    INT       rc;
  2369.    PVOID    pMem;
  2370.  
  2371.    INT       how=0;
  2372.  
  2373.    if( !RXVALIDSTRING(*a) ) {
  2374.       soerr( r, EINVALIDRXSOCKETCALL  );
  2375.       return(0);
  2376.       }
  2377.  
  2378.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  2379.    if( !RXVALIDSTRING(*arg3) ) {
  2380.       soerr( r, EINVALIDRXSOCKETCALL  );
  2381.       return(0);
  2382.       }
  2383.  
  2384.    /*----------------------*/
  2385.    /* Validate "HOW"       */
  2386.    /*----------------------*/
  2387.    if ( (stricmp(arg3->strptr,"TO_ASCII")==0) || 
  2388.         (stricmp(arg3->strptr,"ASCII")==0) ) {
  2389.       cnt = a->strlength;
  2390.       how=1; /* EBCDIC->ASCII */ 
  2391.       }
  2392.    else if ( (stricmp(arg3->strptr,"TO_EBCDIC")==0) || 
  2393.              (stricmp(arg3->strptr,"EBCDIC")==0) )  {
  2394.       cnt = a->strlength;
  2395.       how=2; /* ASCII->EBCDIC */
  2396.       }
  2397.    else if ( (stricmp(arg3->strptr,"TO_IP_ADDRESS")==0) || 
  2398.              (stricmp(arg3->strptr,"TO_IPADDRESS")==0)  ||
  2399.              (stricmp(arg3->strptr,"IPADDRESS")==0) ) {
  2400.       if( a->strlength==4 ) {
  2401.         cnt=-1;
  2402.         how=3; /* HEX->Dotted_Decimal */
  2403.         }
  2404.       else {
  2405.         cnt=4;
  2406.         how=4; /* Dotted_Decimal->HEX */
  2407.         }
  2408.       }
  2409.    else if ( (stricmp(arg3->strptr,"TO_SOCKADDR_IN")==0) || 
  2410.              (stricmp(arg3->strptr,"SOCKADDR_IN")==0) ) {
  2411.       if( a->strlength==16 ) {
  2412.         cnt=-1;
  2413.         how=5; /* HEX->Character */
  2414.         }
  2415.       else {
  2416.         cnt=16;
  2417.         how=6; /* Character->HEX */
  2418.         }  
  2419.       }
  2420.    if( !how ) {
  2421.       soerr( r, EINVALIDRXSOCKETCALL  );
  2422.       return(0);
  2423.       }
  2424.  
  2425.    p = r->strptr;
  2426.    switch( how ) { 
  2427.       case 1:
  2428.          break;
  2429.       case 2:
  2430.          break;
  2431.       case 3:
  2432.          break;
  2433.       case 4:
  2434.          break;
  2435.       case 5:
  2436.          break;
  2437.       case 6:
  2438.          break;
  2439.       } /* end switch */
  2440.  
  2441.    if( cnt>240 ) {  /* Need to get a new RXSTRING for result */
  2442.       rc= DosAllocMem( &pMem, cnt+16, 
  2443.                        PAG_COMMIT|PAG_READ|PAG_WRITE );
  2444.       if( rc ) {
  2445.          soerr( r, ENOMEM );
  2446.          return(0);
  2447.          }
  2448.       r->strptr = pMem;
  2449.       }
  2450.  
  2451.    r->strlength = strlen(r->strptr);
  2452.    return(0);
  2453.    } /* end sotrans */
  2454.  
  2455.  
  2456. /*-----------------------------------*/
  2457. /* VERSION Function (39)             */
  2458. /*-----------------------------------*/
  2459. INT sovers( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2460.    PCH    p;
  2461.  
  2462.    p = r->strptr; 
  2463.    p += sprintf( p, "0 %s", VERSION );
  2464.    r->strlength = strlen(r->strptr);
  2465.    return(0);
  2466.    } /* End sovers */
  2467.  
  2468. /*-----------------------------------*/
  2469. /* WRITE Function (40)               */
  2470. /*-----------------------------------*/
  2471. INT sowrite( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2472.    INT    rc;
  2473.    LONG   s;
  2474.    PRXSTRING arg3;
  2475.  
  2476.    if( string2long(a,&s)==FALSE ) {
  2477.       soerr( r, EINVALIDRXSOCKETCALL );
  2478.       return(0);
  2479.       }
  2480.  
  2481.    arg3 = (PRXSTRING)( (PUCHAR)a + sizeof(RXSTRING) );
  2482.    if( (RXVALIDSTRING(*arg3)) && !(RXZEROLENSTRING(*arg3)) ) 
  2483.       /* continue */ ;
  2484.    else {
  2485.       soerr( r, EINVALIDRXSOCKETCALL  );
  2486.       return(0);
  2487.       }
  2488.    if( arg3->strlength>INT_MAX) {
  2489.       soerr( r, EINVALIDRXSOCKETCALL  );
  2490.       return(0);
  2491.       }
  2492.  
  2493.    rc = write( s, arg3->strptr, arg3->strlength  );
  2494.  
  2495.    if( rc<0 ) {
  2496.       soerr( r, errno );
  2497.       return(0);
  2498.       }
  2499.    strcpy( r->strptr, "0" );
  2500.    r->strlength = strlen(r->strptr);
  2501.    return(0);
  2502.    } /* End sowrite */
  2503.  
  2504. /*-----------------------------------*/
  2505. /* Unimplemented Functions:          */
  2506. /*    GiveSocket                     */
  2507. /*    TakeSocket                     */
  2508. /*    Trace                          */
  2509. /*-----------------------------------*/
  2510. INT sounimpl( ULONG n, PRXSTRING a, PRXSTRING r ) {
  2511.    soerr( r, EINVALIDRXSOCKETCALL );
  2512.    }
  2513.  
  2514. /*-----------------------------------*/
  2515. /* DLL Initialization/Termination    */
  2516. /* (Modified version of default)     */
  2517. /* Most likely never called for Term */
  2518. /*-----------------------------------*/
  2519.   INT _CRT_init (void);
  2520.   VOID _CRT_term (void);
  2521.   VOID __ctordtorInit (void);
  2522.   VOID __ctordtorTerm (void);
  2523.   
  2524. ULONG _DLL_InitTerm ( ULONG mod_handle, ULONG flag )
  2525.   {
  2526.     switch (flag)
  2527.       {
  2528.       case 0:
  2529.         if (_CRT_init () != 0)
  2530.           return 0;
  2531.         __ctordtorInit ();
  2532.        maxsockets = 0;
  2533.        *(Subtaskid) = '\0';
  2534.        return 1;
  2535.       case 1:
  2536.        *(Subtaskid) = '\0';
  2537.        CloseAllSockets();
  2538.         __ctordtorTerm ();
  2539.         /* _CRT_term (); <== Not called */
  2540.         return 1;
  2541.       default:
  2542.         return 0;
  2543.       }
  2544.     return 1;
  2545.   }
  2546. /*-----------------------------------*/
  2547. /* Close all open sockets at DLL     */
  2548. /* termination                       */
  2549. /*-----------------------------------*/
  2550. INT CloseAllSockets( ) {
  2551.    INT i;
  2552.    PSTAB p;
  2553.    INT rc;
  2554.    p = ps;
  2555.    for( i=1; i<=nsock; i++ ) {
  2556.       rc = close( p->stab_snum );
  2557.       p = (PSTAB)( (PUCHAR)p + sizeof(STAB) );
  2558.       }
  2559.    free(ps);
  2560.    maxsockets=0;
  2561.    nsock=0;
  2562.    }
  2563.  
  2564.