rxsock.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2021 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* https://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /***************************************************************************/
39 /* REXX sockets function support */
40 /* sockets utility function package */
41 /***************************************************************************/
42 
43 /*------------------------------------------------------------------
44  * program defines
45  *------------------------------------------------------------------*/
46 #ifdef HAVE_CONFIG_H
47 # include "config.h"
48 #endif
49 
50 #define PROG_DESC "REXX function package for tcp/ip sockets"
51 #define PROG_COPY "(c) Copyright International Business Machines Corporation 1993, 2004"
52 #define PROG_COPY1 "(c) Copyright Rexx Language Association 2005-2014"
53 #define PROG_ALRRa "All Rights Reserved."
54 #define PROG_ALRRb "This program and the accompanying materials"
55 #define PROG_ALRRc "are made available under the terms of the Common Public License v1.0"
56 
57 
58 #ifdef OPSYS_LINUX
59  #define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
60 #endif
61 
62 /*------------------------------------------------------------------
63  * standard includes
64  *------------------------------------------------------------------*/
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 
69 #include <ctype.h>
70 #include <setjmp.h>
71 
72 /*------------------------------------------------------------------
73  * Windows includes
74  *------------------------------------------------------------------*/
75 #if defined(WIN32)
76  #include <winsock.h>
77 #endif
78 
79 /*------------------------------------------------------------------
80  * rexx includes
81  *------------------------------------------------------------------*/
82 #include "oorexxapi.h"
83 
84 /*------------------------------------------------------------------
85  * tcp/ip includes
86  *------------------------------------------------------------------*/
87 #include <sys/types.h>
88 #include <errno.h>
89 
90 #if !defined(WIN32)
91 #include <netdb.h>
92 #include <netinet/in.h>
93 #include <sys/socket.h>
94 #include <arpa/inet.h>
95 #endif
96 
97 /*------------------------------------------------------------------
98  * include for this app
99  *------------------------------------------------------------------*/
100 #include "rxsock.h"
101 
102 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
103 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
104 
105 /*------------------------------------------------------------------
106  * caseless string compare
107  *------------------------------------------------------------------*/
108 int caselessCompare(const char *op1, const char *op2)
109 {
110  for (; tolower(*op1) == tolower(*op2); op1++,op2++)
111  {
112  if (*op1 == 0)
113  {
114  return 0;
115  }
116  }
117 
118  return(tolower(*op1) - tolower(*op2));
119 }
120 
121 /*------------------------------------------------------------------
122  * strip blanks from a line
123  *------------------------------------------------------------------*/
124 void stripBlanks(char *string)
125 {
126  size_t sLen;
127  size_t leading;
128 
129  sLen = strlen(string);
130 
131  /*---------------------------------------------------------------
132  * strip trailing blanks
133  *---------------------------------------------------------------*/
134  while (sLen && (' ' == string[sLen-1]))
135  {
136  string[sLen-1] = 0;
137  }
138 
139  /*---------------------------------------------------------------
140  * strip leading blanks
141  *---------------------------------------------------------------*/
142  leading = strspn(string," ");
143  if (leading)
144  {
145  memmove(string,string+leading,sLen+1);
146  }
147 }
148 
149 
150 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
151 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
152 
153 /*------------------------------------------------------------------
154  * get a rexx stem element as a string value.
155  *------------------------------------------------------------------*/
156 char *getStemElement(RexxCallContext *context, StemManager &stem, const char *name)
157 {
158  // first get the referenced object, returning NULL if it is not set
159  RexxObjectPtr obj = stem.getValue(name);
160  if (obj == NULLOBJECT)
161  {
162  return NULL;
163  }
164 
165  // get this as a copy of the string value, because we may munge this
166  return strdup(context->ObjectToStringValue(obj));
167 }
168 
169 
170 /*------------------------------------------------------------------
171  * convert a stem variable to an array of ints
172  *------------------------------------------------------------------*/
173 void stemToIntArray(RexxCallContext *context, RexxObjectPtr stemSource, int &count, int *&arr)
174 {
175  StemManager stem(context);
176 
177  if (!stem.resolveStem(stemSource))
178  {
179  return;
180  }
181 
182  // set initial values
183  count = 0;
184  arr = NULL;
185 
186  // get the stem.0 item
187  RexxObjectPtr countObj = stem.getValue((size_t)0);
188  if ( countObj == NULLOBJECT )
189  {
190  return;
191  }
192 
193  // try to convert this
194  wholenumber_t temp;
195  if (!context->WholeNumber(countObj, &temp))
196  {
197  return;
198  }
199 
200  /*---------------------------------------------------------------
201  * allocate array
202  *---------------------------------------------------------------*/
203  arr = (int *)malloc(sizeof(int) * temp);
204  if (arr == NULL)
205  {
206  return;
207  }
208 
209  count = (int)temp;
210 
211  /*---------------------------------------------------------------
212  * get each value ...
213  *---------------------------------------------------------------*/
214  for (int i = 0; i < count; i++)
215  {
216  countObj = stem.getValue(i + 1);
217 
218  if (!context->ObjectToWholeNumber(countObj, &temp))
219  {
220  free(arr);
221  arr = NULL;
222  return;
223  }
224  arr[i] = (int)temp;
225  }
226  return;
227 }
228 
229 /*------------------------------------------------------------------
230  * convert an array of ints to a stem variable
231  *------------------------------------------------------------------*/
232 void intArrayToStem(RexxCallContext *context, RexxObjectPtr stemSource, int count, int *arr)
233 {
234  StemManager stem(context);
235 
236  if (!stem.resolveStem(stemSource))
237  {
238  return;
239  }
240 
241  /*---------------------------------------------------------------
242  * set 0'th value
243  *---------------------------------------------------------------*/
244 
245  stem.setValue((size_t)0, context->WholeNumber(count));
246 
247  /*---------------------------------------------------------------
248  * set each value
249  *---------------------------------------------------------------*/
250  for (int i = 0; i < count; i++)
251  {
252  stem.setValue(i + 1, context->WholeNumber(arr[i]));
253  }
254 
255  return;
256 }
257 
258 /*------------------------------------------------------------------
259  * convert a stemmed variable to a sockaddr
260  *------------------------------------------------------------------*/
261 void stemToSockAddr(RexxCallContext *context, StemManager &stem, sockaddr_in *pSockAddr)
262 {
263  char *pszFamily = NULL;
264  char *pszPort = NULL;
265  char *pszAddr = NULL;
266 
267  /*---------------------------------------------------------------
268  * initialize sockaddr
269  *---------------------------------------------------------------*/
270  memset(pSockAddr, 0, sizeof(*pSockAddr));
271 
272  /*---------------------------------------------------------------
273  * get fields
274  *---------------------------------------------------------------*/
275 
276  pszFamily = getStemElement(context, stem, "FAMILY");
277  pszPort = getStemElement(context, stem, "PORT");
278  pszAddr = getStemElement(context, stem, "ADDR");
279 
280  /*---------------------------------------------------------------
281  * if any fields invalid, quit
282  *---------------------------------------------------------------*/
283  if (pszFamily == NULL || pszPort == NULL || pszAddr == NULL)
284  {
285  goto CleanUp;
286  }
287 
288  stripBlanks(pszFamily);
289  stripBlanks(pszPort);
290  stripBlanks(pszAddr);
291 
292  /*---------------------------------------------------------------
293  * get family
294  *---------------------------------------------------------------*/
295  if (!caselessCompare(pszFamily,"AF_INET"))
296  {
297  pSockAddr->sin_family = AF_INET;
298  }
299  else
300  {
301  pSockAddr->sin_family = (short) strtol(pszFamily,NULL,10);
302  }
303 
304  /*---------------------------------------------------------------
305  * get port
306  *---------------------------------------------------------------*/
307  pSockAddr->sin_port = (unsigned short) strtoul(pszPort, NULL, 10);
308  pSockAddr->sin_port = htons(pSockAddr->sin_port);
309 
310  /*---------------------------------------------------------------
311  * get addr
312  *---------------------------------------------------------------*/
313  if (!caselessCompare(pszAddr,"INADDR_ANY"))
314  {
315  pSockAddr->sin_addr.s_addr = INADDR_ANY;
316  }
317  else
318  {
319  pSockAddr->sin_addr.s_addr = inet_addr(pszAddr);
320  }
321 
322  /*------------------------------------------------------------------
323  * clean up and leave
324  *------------------------------------------------------------------*/
325  CleanUp:
326  if (pszFamily == NULL)
327  {
328  free(pszFamily);
329  }
330  if (pszPort == NULL)
331  {
332  free(pszPort);
333  }
334  if (pszAddr == NULL)
335  {
336  free(pszAddr);
337  }
338 }
339 
340 /*------------------------------------------------------------------
341  * convert a sockaddr to a stemmed variable
342  *------------------------------------------------------------------*/
343 void sockAddrToStem(RexxCallContext *context, sockaddr_in *pSockAddr, StemManager &stem )
344 {
345  /*---------------------------------------------------------------
346  * set family
347  *---------------------------------------------------------------*/
348  stem.setValue("FAMILY", context->WholeNumber(pSockAddr->sin_family));
349 
350  /*---------------------------------------------------------------
351  * set port
352  *---------------------------------------------------------------*/
353  stem.setValue("PORT", context->UnsignedInt32(htons(pSockAddr->sin_port)));
354 
355  /*---------------------------------------------------------------
356  * set address
357  *---------------------------------------------------------------*/
358  stem.setValue("ADDR", context->String(inet_ntoa(pSockAddr->sin_addr)));
359 }
360 
361 /*------------------------------------------------------------------
362  * convert a hostent to a stemmed variable
363  *------------------------------------------------------------------*/
364 void hostEntToStem(RexxCallContext *context, struct hostent *pHostEnt, StemManager &stem)
365 {
366  char szBuffer[20];
367  int count;
368  in_addr addr;
369 
370  /*---------------------------------------------------------------
371  * set family
372  *---------------------------------------------------------------*/
373  stem.setValue("NAME", context->String(pHostEnt->h_name));
374 
375  /*---------------------------------------------------------------
376  * set aliases
377  *---------------------------------------------------------------*/
378  for (count=0; pHostEnt->h_aliases[count]; count++)
379  {
380  snprintf(szBuffer, sizeof szBuffer, "ALIAS.%d",count+1);
381  stem.setValue(szBuffer, context->String(pHostEnt->h_aliases[count]));
382  }
383 
384  stem.setValue("ALIAS.0", context->WholeNumber(count));
385 
386  /*---------------------------------------------------------------
387  * set addrtype
388  *---------------------------------------------------------------*/
389  stem.setValue("ADDRTYPE", context->String("AF_INET"));
390 
391  /*---------------------------------------------------------------
392  * set addr
393  *---------------------------------------------------------------*/
394  addr.s_addr = (*(uint32_t *)pHostEnt->h_addr);
395  stem.setValue("ADDR", context->String(inet_ntoa(addr)));
396 
397  /*---------------------------------------------------------------
398  * the stem variable variablename.addr.0 contains count of available
399  * addresses and variablename.addr.n is each address.
400  *
401  * the original form is also returned to preserve compatability
402  * with old applications.
403  *---------------------------------------------------------------
404  *---------------------------------------------------------------
405  * set addresses (note there can be many)
406  *---------------------------------------------------------------*/
407  for (count=0; pHostEnt->h_addr_list[count]; count++)
408  {
409  snprintf(szBuffer, sizeof szBuffer, "ADDR.%d", count+1);
410  addr.s_addr = (*(uint32_t *)pHostEnt->h_addr_list[count]);
411 
412  stem.setValue(szBuffer, context->String(inet_ntoa(addr)));
413  }
414 
415  stem.setValue("ADDR.0", context->WholeNumber(count));
416 }
417 
418 
419 /*------------------------------------------------------------------
420  * convert a string sock option to an integer
421  *------------------------------------------------------------------*/
422 int stringToSockOpt(const char * pszOptName)
423 {
424  if (!pszOptName) return 0;
425 
426  if (!caselessCompare("SO_DEBUG" ,pszOptName)) return SO_DEBUG;
427  else if (!caselessCompare("SO_REUSEADDR" ,pszOptName)) return SO_REUSEADDR;
428  else if (!caselessCompare("SO_KEEPALIVE" ,pszOptName)) return SO_KEEPALIVE;
429  else if (!caselessCompare("SO_DONTROUTE" ,pszOptName)) return SO_DONTROUTE;
430  else if (!caselessCompare("SO_BROADCAST" ,pszOptName)) return SO_BROADCAST;
431  else if (!caselessCompare("SO_USELOOPBACK" ,pszOptName)) return SO_USELOOPBACK;
432  else if (!caselessCompare("SO_LINGER" ,pszOptName)) return SO_LINGER;
433  else if (!caselessCompare("SO_OOBINLINE" ,pszOptName)) return SO_OOBINLINE;
434  else if (!caselessCompare("SO_SNDBUF" ,pszOptName)) return SO_SNDBUF;
435  else if (!caselessCompare("SO_RCVBUF" ,pszOptName)) return SO_RCVBUF;
436  else if (!caselessCompare("SO_SNDLOWAT" ,pszOptName)) return SO_SNDLOWAT;
437  else if (!caselessCompare("SO_RCVLOWAT" ,pszOptName)) return SO_RCVLOWAT;
438  else if (!caselessCompare("SO_SNDTIMEO" ,pszOptName)) return SO_SNDTIMEO;
439  else if (!caselessCompare("SO_RCVTIMEO" ,pszOptName)) return SO_RCVTIMEO;
440  else if (!caselessCompare("SO_ERROR" ,pszOptName)) return SO_ERROR;
441  else if (!caselessCompare("SO_TYPE" ,pszOptName)) return SO_TYPE;
442 
443  return 0;
444 }
445 
446 
447 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
448 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
449 
450 /*------------------------------------------------------------------
451  * set errno
452  *------------------------------------------------------------------*/
453 void setErrno(RexxCallContext *context, bool noError)
454 {
455  char szBuff[20];
456  const char *pszErrno = szBuff;
457  int theErrno;
458 
459  // h_errno is obsolete, but we still set it to 0
460  RexxStringObject zero = context->String("0");
461  context->SetContextVariable("h_errno", zero);
462 
463  // if the function succeeded, errno has no meaning
464  if (noError)
465  {
466  context->SetContextVariable("errno", zero);
467  return;
468  }
469 
470 #if defined(WIN32)
471  theErrno = WSAGetLastError();
472 #else
473  theErrno = errno;
474 #endif
475 
476  switch (theErrno)
477  {
478 #ifdef WIN32
479  case WSAEINTR : pszErrno = "EINTR"; break;
480  case WSAEBADF : pszErrno = "EBADF"; break;
481  case WSAEACCES : pszErrno = "EACCES"; break;
482  case WSAEFAULT : pszErrno = "EFAULT"; break;
483  case WSAEINVAL : pszErrno = "EINVAL"; break;
484  case WSAEMFILE : pszErrno = "EMFILE"; break;
485  case WSAEWOULDBLOCK : pszErrno = "EWOULDBLOCK"; break;
486  case WSAEINPROGRESS : pszErrno = "EINPROGRESS"; break;
487  case WSAEALREADY : pszErrno = "EALREADY"; break;
488  case WSAENOTSOCK : pszErrno = "ENOTSOCK"; break;
489  case WSAEDESTADDRREQ : pszErrno = "EDESTADDRREQ"; break;
490  case WSAEMSGSIZE : pszErrno = "EMSGSIZE"; break;
491  case WSAEPROTOTYPE : pszErrno = "EPROTOTYPE"; break;
492  case WSAENOPROTOOPT : pszErrno = "ENOPROTOOPT"; break;
493  case WSAEPROTONOSUPPORT : pszErrno = "EPROTONOSUPPORT"; break;
494  case WSAESOCKTNOSUPPORT : pszErrno = "ESOCKTNOSUPPORT"; break;
495  case WSAEOPNOTSUPP : pszErrno = "EOPNOTSUPP"; break;
496  case WSAEPFNOSUPPORT : pszErrno = "EPFNOSUPPORT"; break;
497  case WSAEAFNOSUPPORT : pszErrno = "EAFNOSUPPORT"; break;
498  case WSAEADDRINUSE : pszErrno = "EADDRINUSE"; break;
499  case WSAEADDRNOTAVAIL : pszErrno = "EADDRNOTAVAIL"; break;
500  case WSAENETDOWN : pszErrno = "ENETDOWN"; break;
501  case WSAENETUNREACH : pszErrno = "ENETUNREACH"; break;
502  case WSAENETRESET : pszErrno = "ENETRESET"; break;
503  case WSAECONNABORTED : pszErrno = "ECONNABORTED"; break;
504  case WSAECONNRESET : pszErrno = "ECONNRESET"; break;
505  case WSAENOBUFS : pszErrno = "ENOBUFS"; break;
506  case WSAEISCONN : pszErrno = "EISCONN"; break;
507  case WSAENOTCONN : pszErrno = "ENOTCONN"; break;
508  case WSAESHUTDOWN : pszErrno = "ESHUTDOWN"; break;
509  case WSAETOOMANYREFS : pszErrno = "ETOOMANYREFS"; break;
510  case WSAETIMEDOUT : pszErrno = "ETIMEDOUT"; break;
511  case WSAECONNREFUSED : pszErrno = "ECONNREFUSED"; break;
512  case WSAELOOP : pszErrno = "ELOOP"; break;
513  case WSAENAMETOOLONG : pszErrno = "ENAMETOOLONG"; break;
514  case WSAEHOSTDOWN : pszErrno = "EHOSTDOWN"; break;
515  case WSAEHOSTUNREACH : pszErrno = "EHOSTUNREACH"; break;
516  case WSASYSNOTREADY : pszErrno = "WSASYSNOTREADY"; break;
517  case WSAVERNOTSUPPORTED : pszErrno = "WSASAVERNOTSUPPORTED"; break;
518  case WSANOTINITIALISED : pszErrno = "WSANOTINITIALISED"; break;
519  case WSAHOST_NOT_FOUND : pszErrno = "HOST_NOT_FOUND"; break;
520  case WSATRY_AGAIN : pszErrno = "TRY_AGAIN"; break;
521  case WSANO_RECOVERY : pszErrno = "NO_RECOVERY"; break;
522  case WSANO_DATA : pszErrno = "NO_DATA"; break;
523 #else
524 
525  case EWOULDBLOCK : pszErrno = "EWOULDBLOCK"; break;
526  case EINPROGRESS : pszErrno = "EINPROGRESS"; break;
527  case EALREADY : pszErrno = "EALREADY"; break;
528  case ENOTSOCK : pszErrno = "ENOTSOCK"; break;
529  case EDESTADDRREQ : pszErrno = "EDESTADDRREQ"; break;
530  case EMSGSIZE : pszErrno = "EMSGSIZE"; break;
531  case EPROTOTYPE : pszErrno = "EPROTOTYPE"; break;
532  case ENOPROTOOPT : pszErrno = "ENOPROTOOPT"; break;
533  case EPROTONOSUPPORT : pszErrno = "EPROTONOSUPPORT"; break;
534  case ESOCKTNOSUPPORT : pszErrno = "ESOCKTNOSUPPORT"; break;
535  case EOPNOTSUPP : pszErrno = "EOPNOTSUPP"; break;
536  case EPFNOSUPPORT : pszErrno = "EPFNOSUPPORT"; break;
537  case EAFNOSUPPORT : pszErrno = "EAFNOSUPPORT"; break;
538  case EADDRINUSE : pszErrno = "EADDRINUSE"; break;
539  case EADDRNOTAVAIL : pszErrno = "EADDRNOTAVAIL"; break;
540  case ENETDOWN : pszErrno = "ENETDOWN"; break;
541  case ENETUNREACH : pszErrno = "ENETUNREACH"; break;
542  case ENETRESET : pszErrno = "ENETRESET"; break;
543  case ECONNABORTED : pszErrno = "ECONNABORTED"; break;
544  case ECONNRESET : pszErrno = "ECONNRESET"; break;
545  case ENOBUFS : pszErrno = "ENOBUFS"; break;
546  case EISCONN : pszErrno = "EISCONN"; break;
547  case ENOTCONN : pszErrno = "ENOTCONN"; break;
548  case ESHUTDOWN : pszErrno = "ESHUTDOWN"; break;
549  case ETOOMANYREFS : pszErrno = "ETOOMANYREFS"; break;
550  case ETIMEDOUT : pszErrno = "ETIMEDOUT"; break;
551  case ECONNREFUSED : pszErrno = "ECONNREFUSED"; break;
552  case ELOOP : pszErrno = "ELOOP"; break;
553  case ENAMETOOLONG : pszErrno = "ENAMETOOLONG"; break;
554  case EHOSTDOWN : pszErrno = "EHOSTDOWN"; break;
555  case EHOSTUNREACH : pszErrno = "EHOSTUNREACH"; break;
556  case ENOTEMPTY : pszErrno = "ENOTEMPTY"; break;
557 #endif
558  default:
559  snprintf(szBuff, sizeof szBuff, "%d",theErrno);
560  }
561 
562  context->SetContextVariable("errno", context->String(pszErrno));
563 }
564 
565 
566 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
567 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
568 
569 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
570 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
571 
572 /*------------------------------------------------------------------
573  *
574  *------------------------------------------------------------------*/
576 {
577  char buffer[256];
578 
579  snprintf(buffer, sizeof buffer, "%d.%d.%d", ORX_VER, ORX_REL, ORX_MOD);
580  return context->String(buffer);
581 }
582 
583 /*------------------------------------------------------------------
584  * load the function package
585  *------------------------------------------------------------------*/
586 RexxRoutine1(CSTRING, SockLoadFuncs, OPTIONAL_CSTRING, version)
587 {
588  // The rest of this is a NOP now.
589  return "";
590 }
591 
592 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
593 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
594 
595 /*------------------------------------------------------------------
596  * drop the function package
597  *------------------------------------------------------------------*/
599 {
600  // No dropping when used as a package manager.
601  return context->NullString();
602 }
603 
604 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
605 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
606 
607 /*------------------------------------------------------------------
608  * cause a trap to unload the DLL
609  *------------------------------------------------------------------*/
610 RexxRoutine0(int, SockDie)
611 {
612  return 0;
613 }
614 
615 
616 /**
617  * A loader to perform an startup initialization
618  *
619  * @param context The loader thread context
620  *
621  * @return nothing
622  */
624 {
625 // Windows requires the sockets system to be updated on a per-process basis.
626 #ifdef WIN32
627  WORD wVersionRequested;
628  WSADATA wsaData;
629  wVersionRequested = MAKEWORD( 1, 1 );
630  int rc = WSAStartup( wVersionRequested, &wsaData );
631 #endif
632 }
633 
634 /*------------------------------------------------------------------
635  * declare external functions
636  *------------------------------------------------------------------*/
637 
646 REXX_TYPED_ROUTINE_PROTOTYPE(SockGetHostByAddr);
647 REXX_TYPED_ROUTINE_PROTOTYPE(SockGetHostByName);
667 
668 
669 // now build the actual entry list
671 {
672  REXX_TYPED_ROUTINE( SockLoadFuncs, SockLoadFuncs),
673  REXX_TYPED_ROUTINE( SockDropFuncs, SockDropFuncs),
674  REXX_TYPED_ROUTINE( SockAccept, SockAccept),
675  REXX_TYPED_ROUTINE( SockBind, SockBind),
676  REXX_TYPED_ROUTINE( SockClose, SockClose),
677  REXX_TYPED_ROUTINE( SockConnect, SockConnect),
678  REXX_TYPED_ROUTINE( SockGetHostByAddr, SockGetHostByAddr),
679  REXX_TYPED_ROUTINE( SockGetHostByName, SockGetHostByName),
680  REXX_TYPED_ROUTINE( SockGetHostId, SockGetHostId),
681  REXX_TYPED_ROUTINE( SockGetHostName, SockGetHostName),
682  REXX_TYPED_ROUTINE( SockGetPeerName, SockGetPeerName),
683  REXX_TYPED_ROUTINE( SockGetSockName, SockGetSockName),
684  REXX_TYPED_ROUTINE( SockGetSockOpt, SockGetSockOpt),
685  REXX_TYPED_ROUTINE( SockInit, SockInit),
686  REXX_TYPED_ROUTINE( SockIoctl, SockIoctl),
687  REXX_TYPED_ROUTINE( SockListen, SockListen),
688  REXX_TYPED_ROUTINE( SockPSock_Errno, SockPSock_Errno),
689  REXX_TYPED_ROUTINE( SockRecv, SockRecv),
690  REXX_TYPED_ROUTINE( SockRecvFrom, SockRecvFrom),
691  REXX_TYPED_ROUTINE( SockSelect, SockSelect),
692  REXX_TYPED_ROUTINE( SockSend, SockSend),
693  REXX_TYPED_ROUTINE( SockSendTo, SockSendTo),
694  REXX_TYPED_ROUTINE( SockSetSockOpt, SockSetSockOpt),
695  REXX_TYPED_ROUTINE( SockShutDown, SockShutDown),
696  REXX_TYPED_ROUTINE( SockSock_Errno, SockSock_Errno),
697  REXX_TYPED_ROUTINE( SockSocket, SockSocket),
698  REXX_TYPED_ROUTINE( SockSoClose, SockClose),
699  REXX_TYPED_ROUTINE( SockVersion, SockVersion),
701 };
702 
704 {
706  REXX_INTERPRETER_4_0_0, // anything after 4.0.0 will work
707  "rxsock", // name of the package
708  "4.0", // package information
709  loader, // we have some load time initialization
710  NULL, // but nothing to do at unload
711  rxsock_functions, // the exported functions
712  NULL // no methods in this package
713 };
714 
715 // package loading stub.
RexxObjectPtr getValue(const char *name)
Definition: rxsock.h:222
bool resolveStem(RexxObjectPtr source)
Definition: rxsock.h:124
void setValue(const char *name, RexxObjectPtr value)
Definition: rxsock.h:181
#define REXX_INTERPRETER_4_0_0
Definition: oorexxapi.h:216
#define REXX_LAST_ROUTINE()
Definition: oorexxapi.h:193
#define REXX_TYPED_ROUTINE(n, e)
Definition: oorexxapi.h:191
#define STANDARD_PACKAGE_HEADER
Definition: oorexxapi.h:230
const char * CSTRING
Definition: rexx.h:78
struct _RexxStringObject * RexxStringObject
Definition: rexx.h:128
struct _RexxObjectPtr * RexxObjectPtr
Definition: rexx.h:127
#define NULLOBJECT
Definition: rexx.h:147
ssize_t wholenumber_t
Definition: rexx.h:230
#define RexxEntry
Definition: rexx.h:235
void setErrno(RexxCallContext *context, bool noError)
Definition: rxsock.cpp:453
char * getStemElement(RexxCallContext *context, StemManager &stem, const char *name)
Definition: rxsock.cpp:156
int stringToSockOpt(const char *pszOptName)
Definition: rxsock.cpp:422
void stemToSockAddr(RexxCallContext *context, StemManager &stem, sockaddr_in *pSockAddr)
Definition: rxsock.cpp:261
void hostEntToStem(RexxCallContext *context, struct hostent *pHostEnt, StemManager &stem)
Definition: rxsock.cpp:364
REXX_TYPED_ROUTINE_PROTOTYPE(SockDropFuncs)
RexxRoutine1(CSTRING, SockLoadFuncs, OPTIONAL_CSTRING, version)
Definition: rxsock.cpp:586
RexxPackageEntry rxsock_package_entry
Definition: rxsock.cpp:703
void sockAddrToStem(RexxCallContext *context, sockaddr_in *pSockAddr, StemManager &stem)
Definition: rxsock.cpp:343
int caselessCompare(const char *op1, const char *op2)
Definition: rxsock.cpp:108
void intArrayToStem(RexxCallContext *context, RexxObjectPtr stemSource, int count, int *arr)
Definition: rxsock.cpp:232
RexxRoutineEntry rxsock_functions[]
Definition: rxsock.cpp:670
void stripBlanks(char *string)
Definition: rxsock.cpp:124
void RexxEntry loader(RexxThreadContext *context)
Definition: rxsock.cpp:623
void stemToIntArray(RexxCallContext *context, RexxObjectPtr stemSource, int &count, int *&arr)
Definition: rxsock.cpp:173
RexxRoutine0(RexxStringObject, SockVersion)
Definition: rxsock.cpp:575
OOREXX_GET_PACKAGE(rxsock)
struct sockaddr_in sockaddr_in
Definition: rxsock.h:48
struct in_addr in_addr
Definition: rxsock.h:49
Definition: oorexxapi.h:242
Definition: oorexxapi.h:177
unsigned int uint32_t