rxsockfn.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 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 /* http://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 rxsockfn.c */
40 /* sockets utility function package */
41 /***************************************************************************/
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 
50 #include <ctype.h>
51 #include <setjmp.h>
52 
53 /*------------------------------------------------------------------
54  * rexx includes
55  *------------------------------------------------------------------*/
56 # include "oorexxapi.h"
57 /*------------------------------------------------------------------
58  * tcp/ip includes
59  *------------------------------------------------------------------*/
60 #include <sys/types.h>
61 #include <errno.h>
62 
63 #if !defined(WIN32)
64 #include <netdb.h>
65 #include <netinet/in.h>
66 #include <arpa/inet.h>
67 # ifdef __APPLE__
68  // need to define this for Mac OSX 10.2
69 #define _BSD_SOCKLEN_T_
70 #endif
71 #include <sys/socket.h>
72 #include <sys/ioctl.h>
73 #include <sys/time.h>
74 #include <unistd.h>
75 
76 #if defined( HAVE_SYS_SELECT_H )
77 #include <sys/select.h>
78 #endif
79 #if defined( HAVE_SYS_FILIO_H )
80 #include <sys/filio.h>
81 #endif
82 #endif
83 
84 #define psock_errno(s) fprintf(stderr, "RxSOCK Error: %s\n", s)
85 
86 #if defined(WIN32) // define errno equivalents for windows
87  #define sock_errno() WSAGetLastError()
88 #else
89  #define sock_errno() errno
90 #endif
91 
92 /*------------------------------------------------------------------
93  * include for this app
94  *------------------------------------------------------------------*/
95 #include "rxsock.h"
96 
97 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
98 //#if !defined(WIN32)
99 //extern int h_errno; // where is this used?
100 //#endif
101 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
102 
103 /*------------------------------------------------------------------
104  * sock_errno()
105  *------------------------------------------------------------------*/
106 RexxRoutine0(int, SockSock_Errno)
107 {
108  return sock_errno();
109 }
110 
111 
112 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
113 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
114 
115 /*------------------------------------------------------------------
116  * psock_errno()
117  *------------------------------------------------------------------*/
118 RexxRoutine1(CSTRING, SockPSock_Errno, OPTIONAL_CSTRING, type)
119 {
120  if (type == NULL)
121  {
122  type = "";
123  }
124  psock_errno(type);
125  return "";
126 }
127 
128 
129 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
130 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
131 
132 /*------------------------------------------------------------------------------
133  * accept()
134  *
135  * @remarks The sockAddrToStem() function calls both htons() and inet_ntoa().
136  * On Windows, one or both, of those functions sets errno back to 0.
137  * This prevents the Rexx programmer from ever seeing the errno if
138  * accept fails. Because of this, we call cleanup() immediately after
139  * the accept call in the belief that the Rexx programmer is more
140  * interested in the result of accept().
141 * ----------------------------------------------------------------------------*/
142 RexxRoutine2(int, SockAccept, int, sock, OPTIONAL_RexxObjectPtr, stemSource)
143 {
144  sockaddr_in addr;
145  socklen_t nameLen;
146 
147  nameLen = sizeof(addr);
148  int rc = accept(sock, (struct sockaddr *)&addr, &nameLen);
149 
150  // set the errno variables
151  cleanup(context);
152 
153  /*---------------------------------------------------------------
154  * set addr, if asked for
155  *---------------------------------------------------------------*/
156  if (stemSource != NULLOBJECT)
157  {
158  StemManager stem(context);
159 
160  if (!stem.resolveStem(stemSource))
161  {
162  return 0;
163  }
164  sockAddrToStem(context, &addr, stem);
165  }
166 
167  return rc;
168 }
169 
170 
171 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
172 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
173 
174 /*------------------------------------------------------------------
175  * bind()
176  *------------------------------------------------------------------*/
177 RexxRoutine2(int, SockBind, int, sock, RexxObjectPtr, stemSource)
178 {
179  StemManager stem(context);
180 
181  if (!stem.resolveStem(stemSource))
182  {
183  return 0;
184  }
185 
186  sockaddr_in addr;
187 
188  /*---------------------------------------------------------------
189  * get addr
190  *---------------------------------------------------------------*/
191  stemToSockAddr(context, stem, &addr);
192 
193  /*---------------------------------------------------------------
194  * call function
195  *---------------------------------------------------------------*/
196  int rc = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
197  // make sure the errno variables are set
198  cleanup(context);
199  return rc;
200 }
201 
202 
203 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
204 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
205 
206 /*------------------------------------------------------------------
207  * close()
208  *------------------------------------------------------------------*/
209 RexxRoutine1(int, SockClose, int, sock)
210 {
211  /*---------------------------------------------------------------
212  * call function
213  *---------------------------------------------------------------*/
214 #if defined(WIN32)
215  int rc = closesocket(sock);
216 #else
217  int rc = close(sock);
218 #endif
219  // set the errno information
220  cleanup(context);
221 
222  return rc;
223 }
224 
225 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
226 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
227 
228 /*------------------------------------------------------------------
229  * connect()
230  *------------------------------------------------------------------*/
231 RexxRoutine2(int, SockConnect, int, sock, RexxObjectPtr, stemSource)
232 {
233  StemManager stem(context);
234 
235  if (!stem.resolveStem(stemSource))
236  {
237  return 0;
238  }
239 
240  sockaddr_in addr;
241 
242  /*---------------------------------------------------------------
243  * get addr
244  *---------------------------------------------------------------*/
245  stemToSockAddr(context, stem, &addr);
246 
247  /*---------------------------------------------------------------
248  * call function
249  *---------------------------------------------------------------*/
250  int rc = connect(sock,(struct sockaddr *)&addr, sizeof(addr));
251  // set the errno information
252  cleanup(context);
253 
254  return rc;
255 }
256 
257 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
258 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
259 
260 /*------------------------------------------------------------------
261  * gethostbyaddr()
262  *------------------------------------------------------------------*/
263 RexxRoutine3(int, SockGetHostByAddr, CSTRING, addrArg, RexxObjectPtr, stemSource, OPTIONAL_int, domain)
264 {
265  struct hostent *pHostEnt;
266  in_addr addr;
267 
268  StemManager stem(context);
269 
270  if (!stem.resolveStem(stemSource))
271  {
272  return 0;
273  }
274 
275  addr.s_addr = inet_addr(addrArg);
276 
277  if (argumentOmitted(3))
278  {
279  domain = AF_INET;
280  }
281 
282  /*---------------------------------------------------------------
283  * call function
284  *---------------------------------------------------------------*/
285  pHostEnt = gethostbyaddr((char*)&addr, sizeof(addr), domain);
286  // set the errno information
287  cleanup(context);
288 
289  if (!pHostEnt)
290  {
291  return 0;
292  }
293  else
294  {
295  hostEntToStem(context, pHostEnt, stem);
296  return 1;
297  }
298 }
299 
300 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
301 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
302 
303 /*------------------------------------------------------------------
304  * gethostbyname()
305  *------------------------------------------------------------------*/
306 RexxRoutine2(int, SockGetHostByName, CSTRING, name, RexxObjectPtr, stemSource)
307 {
308  StemManager stem(context);
309 
310  if (!stem.resolveStem(stemSource))
311  {
312  return 0;
313  }
314  struct hostent *pHostEnt;
315 
316  /*---------------------------------------------------------------
317  * call function
318  *---------------------------------------------------------------*/
319  pHostEnt = gethostbyname(name);
320  // set the errno information
321  cleanup(context);
322 
323  if (!pHostEnt)
324  {
325  return 0;
326  }
327  else
328  {
329  hostEntToStem(context, pHostEnt, stem);
330  return 1;
331  }
332 }
333 
334 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
335 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
336 
337 /*------------------------------------------------------------------
338  * gethostid()
339  *------------------------------------------------------------------*/
341 {
342  in_addr ia;
343 #ifdef WIN32
344  char pszBuff[64]; // buffer for ip address
345  PHOSTENT pHostEnt; // ptr to hostent structure
346  /*
347  * Retrieve my ip address. Assuming the hosts file in
348  * in %systemroot%/system/drivers/etc/hosts contains my computer name.
349  */ //get our name
350  if (gethostname(pszBuff, sizeof(pszBuff)))
351  {
352  // set the errno information
353  cleanup(context);
354  return context->String("0.0.0.0");
355  }
356  pHostEnt = gethostbyname(pszBuff); // get our ip address
357  if (!pHostEnt)
358  {
359  // set the errno information
360  cleanup(context);
361  return context->String("0.0.0.0");
362  }
363  ia.s_addr = (*(uint32_t *)pHostEnt->h_addr);// in network byte order already
364  return context->String(inet_ntoa(ia));
365 #else
366 #if defined(OPSYS_AIX) || defined(OPSYS_LINUX)
367 #define h_addr h_addr_list[0]
368 
369  char pszBuff[64]; /* buffer for ip address*/
370  struct hostent * pHostEnt; /* ptr to hostent structure*/
371 
372  /*get our name*/
373  if (gethostname(pszBuff, sizeof(pszBuff)))
374  {
375  // set the errno information
376  cleanup(context);
377  return context->String("0.0.0.0");
378  }
379  pHostEnt = gethostbyname(pszBuff); /* get our ip address */
380  // set the errno information
381  cleanup(context);
382  if (!pHostEnt)
383  {
384  return context->String("0.0.0.0");
385  }
386  ia.s_addr = (*(uint32_t *)pHostEnt->h_addr);// in network byte order already
387  return context->String(inet_ntoa(ia));
388 #else
389  ia.s_addr = htonl(gethostid());
390  // set the errno information
391  cleanup(context);
392  return context->String(inet_ntoa(ia));
393 #endif
394 #endif
395 }
396 
397 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
398 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
399 
400 /*------------------------------------------------------------------
401  * gethostname()
402  *------------------------------------------------------------------*/
404 {
405  char pszBuff[256]; /* host names are limited to 255 bytes */
406  *pszBuff = '\0';
407 
408  /*
409  * Assuming the hosts file in
410  * in %systemroot%/system/drivers/etc/hosts contains my computer name.
411  */
412  int rc = gethostname(pszBuff, sizeof(pszBuff));
413 
414  // set the errno information
415  cleanup(context);
416 
417  return context->String(pszBuff);
418 }
419 
420 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
421 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
422 
423 /*------------------------------------------------------------------
424  * getpeername()
425  *------------------------------------------------------------------*/
426 RexxRoutine2(int, SockGetPeerName, int, sock, RexxObjectPtr, stemSource)
427 {
428  StemManager stem(context);
429 
430  if (!stem.resolveStem(stemSource))
431  {
432  return 0;
433  }
434  sockaddr_in addr;
435  socklen_t nameLen;
436 
437  /*---------------------------------------------------------------
438  * call function
439  *---------------------------------------------------------------*/
440  nameLen = sizeof(addr);
441  int rc = getpeername(sock,(struct sockaddr *)&addr,&nameLen);
442 
443  // set the errno information
444  cleanup(context);
445 
446  /*---------------------------------------------------------------
447  * write address to stem
448  *---------------------------------------------------------------*/
449  sockAddrToStem(context, &addr, stem);
450 
451  /*---------------------------------------------------------------
452  * set return code
453  *---------------------------------------------------------------*/
454  return rc;
455 }
456 
457 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
458 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
459 
460 /*------------------------------------------------------------------
461  * getsockname()
462  *------------------------------------------------------------------*/
463 RexxRoutine2(int, SockGetSockName, int, sock, RexxObjectPtr, stemSource)
464 {
465  StemManager stem(context);
466 
467  if (!stem.resolveStem(stemSource))
468  {
469  return 0;
470  }
471  sockaddr_in addr;
472  socklen_t nameLen;
473 
474  /*---------------------------------------------------------------
475  * call function
476  *---------------------------------------------------------------*/
477  nameLen = sizeof(addr);
478  int rc = getsockname(sock,(struct sockaddr *)&addr,&nameLen);
479  // set the errno information
480  cleanup(context);
481 
482  /*---------------------------------------------------------------
483  * write address to stem
484  *---------------------------------------------------------------*/
485  sockAddrToStem(context, &addr, stem);
486 
487  /*---------------------------------------------------------------
488  * set return code
489  *---------------------------------------------------------------*/
490  return rc;
491 }
492 
493 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
494 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
495 
496 /*------------------------------------------------------------------
497  * getsockopt()
498  *------------------------------------------------------------------*/
499 RexxRoutine4(int, SockGetSockOpt, int, sock, CSTRING, level, CSTRING, option, CSTRING, var)
500 {
501  struct linger lingStruct;
502  socklen_t len;
503  void *ptr;
504  char buffer[30];
505 
506 
507  if (caselessCompare("SOL_SOCKET", level) != 0)
508  {
509  context->InvalidRoutine();
510  return 0;
511  }
512 
513  /*---------------------------------------------------------------
514  * get option name
515  *---------------------------------------------------------------*/
516  int opt = stringToSockOpt(option);
517 
518  /*---------------------------------------------------------------
519  * set up buffer
520  *---------------------------------------------------------------*/
521  int intVal = 0;
522 
523  switch (opt)
524  {
525  case SO_LINGER:
526  ptr = &lingStruct;
527  len = sizeof(lingStruct);
528  break;
529 
530  default:
531  ptr = &intVal;
532  len = sizeof(int);
533  }
534 
535  /*---------------------------------------------------------------
536  * make call
537  *---------------------------------------------------------------*/
538  int rc = getsockopt(sock,SOL_SOCKET,opt,(char *)ptr,&len);
539 
540  // set the errno information
541  cleanup(context);
542 
543  /*---------------------------------------------------------------
544  * set return value
545  *---------------------------------------------------------------*/
546  switch (opt)
547  {
548  case SO_LINGER:
549  sprintf(buffer,"%d %d", lingStruct.l_onoff, lingStruct.l_linger);
550  break;
551 
552  case SO_TYPE:
553  switch (intVal)
554  {
555  case SOCK_STREAM: strcpy(buffer,"STREAM"); break;
556  case SOCK_DGRAM: strcpy(buffer,"DGRAM"); break;
557  case SOCK_RAW: strcpy(buffer,"RAW"); break;
558  default: strcpy(buffer,"UNKNOWN");
559  }
560  break;
561 
562  default:
563  sprintf(buffer,"%d", intVal);
564  }
565 
566  // set the variable
567  context->SetContextVariable(var, context->String(buffer));
568  return rc;
569 }
570 
571 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
572 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
573 
574 /*------------------------------------------------------------------
575  * ioctl()
576  *------------------------------------------------------------------*/
577 RexxRoutine3(int, SockIoctl, int, sock, CSTRING, command, RexxObjectPtr, var)
578 {
579  int cmd = 0;
580  void *data;
581  int dataBuff;
582  int len;
583  int rc;
584 
585  if (!caselessCompare(command, "FIONBIO"))
586  {
587  cmd = FIONBIO;
588  int32_t temp;
589 
590  if (!context->Int32(var, &temp))
591  {
592  context->InvalidRoutine();
593  return 0;
594  }
595  dataBuff = (int)temp;
596  data = &dataBuff;
597  len = sizeof(int);
598  }
599  else if (!caselessCompare(command, "FIONREAD"))
600  {
601  cmd = FIONREAD;
602  data = &dataBuff;
603  len = sizeof(dataBuff);
604  }
605  else
606  {
607  return -1;
608  }
609 
610  /*---------------------------------------------------------------
611  * make call
612  *---------------------------------------------------------------*/
613 #ifdef WIN32
614  rc = ioctlsocket(sock,cmd,(u_long *)data);
615 #else
616  rc = ioctl(sock,cmd,data,len);
617 #endif
618 
619  // set the errno information
620  cleanup(context);
621 
622  /*---------------------------------------------------------------
623  * set output for FIONREAD
624  *---------------------------------------------------------------*/
625  if (cmd == FIONREAD)
626  {
627  context->SetContextVariable(context->ObjectToStringValue(var), context->Int32(dataBuff));
628  }
629 
630  return rc;
631 }
632 
633 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
634 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
635 
636 /*------------------------------------------------------------------
637  * listen()
638  *------------------------------------------------------------------*/
639 RexxRoutine2(int, SockListen, int, sock, int, backlog)
640 {
641  /*---------------------------------------------------------------
642  * call function
643  *---------------------------------------------------------------*/
644  int rc = listen(sock, backlog);
645 
646  // set the errno information
647  cleanup(context);
648  return rc;
649 }
650 
651 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
652 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
653 
654 /*------------------------------------------------------------------
655  * recv()
656  *------------------------------------------------------------------*/
657 RexxRoutine4(int, SockRecv, int, sock, CSTRING, var, int, dataLen, OPTIONAL_CSTRING, flagVal)
658 {
659  int flags;
660  long rc;
661  char *pBuffer;
662 
663  /*---------------------------------------------------------------
664  * get flags
665  *---------------------------------------------------------------*/
666  flags = 0;
667  if (flagVal != NULL)
668  {
669  char *flagStr = strdup(flagVal);
670  if (flagStr == NULL)
671  {
672  context->InvalidRoutine();
673  return 0;
674  }
675  const char *pszWord = strtok(flagStr, " ");
676  while (pszWord)
677  {
678  if (!caselessCompare(pszWord,"MSG_OOB")) flags |= MSG_OOB;
679  else if (!caselessCompare(pszWord,"MSG_PEEK")) flags |= MSG_PEEK;
680  pszWord = strtok(NULL," ");
681  }
682  free(flagStr);
683  }
684 
685  /*---------------------------------------------------------------
686  * allocate memory for data
687  *---------------------------------------------------------------*/
688  pBuffer = (char *)malloc(dataLen);
689  if (!pBuffer)
690  {
691  context->InvalidRoutine();
692  return 0;
693  }
694 
695  /*---------------------------------------------------------------
696  * call function
697  *---------------------------------------------------------------*/
698  rc = recv(sock, pBuffer, dataLen, flags);
699 
700  // set the errno information
701  cleanup(context);
702 
703  if (-1 == rc)
704  {
705  dataLen = 0;
706  }
707  else
708  {
709  dataLen = rc;
710  }
711 
712  context->SetContextVariable(var, context->String(pBuffer, dataLen));
713 
714  free(pBuffer);
715 
716  /*---------------------------------------------------------------
717  * set return code
718  *---------------------------------------------------------------*/
719  return rc;
720 }
721 
722 
723 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
724 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
725 
726 /*------------------------------------------------------------------
727  * recvfrom()
728  *------------------------------------------------------------------*/
729 RexxRoutine5(int, SockRecvFrom, int, sock, CSTRING, var, int, dataLen, RexxObjectPtr, flagArg, OPTIONAL_RexxObjectPtr, stemSource)
730 {
731  StemManager stem(context);
732  sockaddr_in addr;
733  socklen_t addr_size;
734 
735 
736  /*---------------------------------------------------------------
737  * get flags
738  *---------------------------------------------------------------*/
739  int flags = 0;
740  // if we have a 5th argument, then the 4th argument is a flag value
741  if (stemSource != NULL)
742  {
743  if (!stem.resolveStem(stemSource))
744  {
745  return 0;
746  }
747 
748  char *flagStr = strdup(context->ObjectToStringValue(flagArg));
749 
750  const char *pszWord = strtok(flagStr, " ");
751  while (pszWord)
752  {
753  if (!caselessCompare(pszWord,"MSG_OOB"))
754  {
755  flags |= MSG_OOB;
756  }
757  else if (!caselessCompare(pszWord,"MSG_PEEK"))
758  {
759  flags |= MSG_PEEK;
760  }
761  pszWord = strtok(NULL," ");
762  }
763  free(flagStr);
764  }
765  else
766  {
767  // the 4th argument is a stem variable
768  if (!stem.resolveStem(flagArg))
769  {
770  return 0;
771  }
772  }
773 
774  stemToSockAddr(context, stem, &addr);
775  addr_size=sizeof(addr);
776 
777  /*---------------------------------------------------------------
778  * allocate memory for data
779  *---------------------------------------------------------------*/
780  char *pBuffer = (char *)malloc(dataLen);
781  if (!pBuffer)
782  {
783  context->InvalidRoutine();
784  return 0;
785  }
786 
787  /*---------------------------------------------------------------
788  * call function
789  *---------------------------------------------------------------*/
790  int rc = recvfrom(sock,pBuffer,dataLen,flags,(struct sockaddr *)&addr,&addr_size);
791 
792  // set the errno information
793  cleanup(context);
794 
795  if (-1 == rc)
796  {
797  dataLen = 0;
798  }
799  else
800  {
801  dataLen = rc;
802  }
803 
804  sockAddrToStem(context, &addr, stem);
805 
806  context->SetContextVariable(var, context->String(pBuffer, dataLen));
807 
808  free(pBuffer);
809 
810  /*---------------------------------------------------------------
811  * set return code
812  *---------------------------------------------------------------*/
813  return rc;
814 }
815 
816 
817 
818 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
819 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
820 /*------------------------------------------------------------------
821  * select()
822  *------------------------------------------------------------------*/
823 RexxRoutine4(int, SockSelect, OPTIONAL_RexxObjectPtr, array1, OPTIONAL_RexxObjectPtr, array2, OPTIONAL_RexxObjectPtr, array3, OPTIONAL_int, timeout)
824 {
825  struct timeval timeOutS;
826  struct timeval *timeOutP;
827  int rCount = 0;
828  int wCount = 0;
829  int eCount = 0;
830  int *rArray = NULL;
831  int *wArray = NULL;
832  int *eArray = NULL;
833  int i;
834  int j;
835  int rc;
836 #if defined(OPSYS_LINUX)
837  fd_set rSetS, *rSet = &rSetS;
838  fd_set wSetS, *wSet = &wSetS;
839  fd_set eSetS, *eSet = &eSetS;
840 #else
841  struct fd_set rSetS, *rSet = &rSetS;
842  struct fd_set wSetS, *wSet = &wSetS;
843  struct fd_set eSetS, *eSet = &eSetS;
844 #endif
845  int max;
846 
847  /*---------------------------------------------------------------
848  * get timeout value
849  *---------------------------------------------------------------*/
850  if (argumentOmitted(4))
851  {
852  timeOutP = NULL;
853  }
854  else
855  {
856  if (timeout < 0)
857  {
858  timeout = 0;
859  }
860 
861  timeOutS.tv_sec = timeout;
862  timeOutS.tv_usec = 0;
863  timeOutP = &timeOutS;
864  }
865 
866  /*---------------------------------------------------------------
867  * get arrays of sockets
868  *---------------------------------------------------------------*/
869  stemToIntArray(context, array1, rCount, rArray);
870  stemToIntArray(context, array2, wCount, wArray);
871  stemToIntArray(context, array3, eCount, eArray);
872 
873 /*------------------------------------------------------------------
874  * unix-specific stuff
875  *------------------------------------------------------------------*/
876  /*---------------------------------------------------------------
877  * fill in fd_set's
878  *---------------------------------------------------------------*/
879  FD_ZERO(rSet);
880  FD_ZERO(wSet);
881  FD_ZERO(eSet);
882 
883  for (i=0; i<rCount; i++)
884  {
885  FD_SET(rArray[i],rSet);
886  }
887  for (i=0; i<wCount; i++)
888  {
889  FD_SET(wArray[i],wSet);
890  }
891  for (i=0; i<eCount; i++)
892  {
893  FD_SET(eArray[i],eSet);
894  }
895 
896  /*---------------------------------------------------------------
897  * get max number
898  *---------------------------------------------------------------*/
899  max = 0;
900  for (i=0; i<rCount; i++)
901  {
902  if (rArray[i] > max)
903  {
904  max = rArray[i];
905  }
906  }
907 
908  for (i=0; i<wCount; i++)
909  {
910  if (wArray[i] > max)
911  {
912  max = wArray[i];
913  }
914  }
915 
916  for (i=0; i<eCount; i++)
917  {
918  if (eArray[i] > max)
919  {
920  max = eArray[i];
921  }
922  }
923 
924  /*---------------------------------------------------------------
925  * make the call
926  *---------------------------------------------------------------*/
927  rc = select(max+1,rSet,wSet,eSet,timeOutP);
928 
929  // set the errno information
930  cleanup(context);
931 
932  /*---------------------------------------------------------------
933  * fix up the socket arrays
934  *---------------------------------------------------------------*/
935  if (rc != 0)
936  {
937  j = 0;
938  for (i=0; i<rCount; i++)
939  {
940  if (FD_ISSET(rArray[i],rSet))
941  {
942  rArray[j] = rArray[i];
943  j++;
944  }
945  }
946  rCount = j;
947 
948  j = 0;
949  for (i=0; i<wCount; i++)
950  {
951  if (FD_ISSET(wArray[i],wSet))
952  {
953  wArray[j] = wArray[i];
954  j++;
955  }
956  }
957  wCount = j;
958 
959  j = 0;
960  for (i=0; i<eCount; i++)
961  {
962  if (FD_ISSET(eArray[i],eSet))
963  {
964  eArray[j] = eArray[i];
965  j++;
966  }
967  }
968  eCount = j;
969  }
970 
971 
972  /*---------------------------------------------------------------
973  * reset the stem variables
974  *---------------------------------------------------------------*/
975  if (rArray)
976  {
977  intArrayToStem(context, array1, rCount, rArray);
978  }
979  if (wArray)
980  {
981  intArrayToStem(context, array2, wCount, wArray);
982  }
983  if (eArray)
984  {
985  intArrayToStem(context, array3, eCount, eArray);
986  }
987 
988  /*---------------------------------------------------------------
989  * free arrays
990  *---------------------------------------------------------------*/
991  if (rArray)
992  {
993  free(rArray);
994  }
995  if (wArray)
996  {
997  free(wArray);
998  }
999  if (eArray)
1000  {
1001  free(eArray);
1002  }
1003 
1004  /*---------------------------------------------------------------
1005  * set return code
1006  *---------------------------------------------------------------*/
1007  return rc;
1008 }
1009 
1010 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1011 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1012 
1013 /*------------------------------------------------------------------
1014  * send()
1015  *------------------------------------------------------------------*/
1016 RexxRoutine3(int, SockSend, int, sock, RexxStringObject, dataObj, OPTIONAL_CSTRING, flagArg)
1017 {
1018  /*---------------------------------------------------------------
1019  * get data length
1020  *---------------------------------------------------------------*/
1021  size_t dataLen = context->StringLength(dataObj);
1022  const char *data = context->StringData(dataObj);
1023 
1024  /*---------------------------------------------------------------
1025  * get flags
1026  *---------------------------------------------------------------*/
1027  int flags = 0;
1028  if (flagArg != NULL)
1029  {
1030  char *flagStr = strdup(flagArg);
1031  if (flagStr == NULL)
1032  {
1033  context->InvalidRoutine();
1034  return 0;
1035  }
1036 
1037  const char *pszWord = strtok(flagStr, " ");
1038  while (pszWord)
1039  {
1040  if (!caselessCompare(pszWord,"MSG_OOB"))
1041  {
1042  flags |= MSG_OOB;
1043  }
1044  else if (!caselessCompare(pszWord,"MSG_DONTROUTE"))
1045  {
1046  flags |= MSG_DONTROUTE;
1047  }
1048 
1049  pszWord = strtok(NULL," ");
1050  }
1051  free(flagStr);
1052  }
1053 
1054  /*---------------------------------------------------------------
1055  * call function
1056  *---------------------------------------------------------------*/
1057  int rc = send(sock,data,dataLen,flags);
1058 
1059  // set the errno information
1060  cleanup(context);
1061 
1062  /*---------------------------------------------------------------
1063  * set return code
1064  *---------------------------------------------------------------*/
1065  return rc;
1066 }
1067 
1068 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1069 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1070 
1071 /*------------------------------------------------------------------
1072  * sendto()
1073  *------------------------------------------------------------------*/
1074 RexxRoutine4(int, SockSendTo, int, sock, RexxStringObject, dataObj, RexxObjectPtr, flagsOrStem, OPTIONAL_RexxObjectPtr, stemSource)
1075 {
1076  StemManager stem(context);
1077 
1078  sockaddr_in addr;
1079 
1080  /*---------------------------------------------------------------
1081  * get data length
1082  *---------------------------------------------------------------*/
1083  int dataLen = context->StringLength(dataObj);
1084  const char *data = context->StringData(dataObj);
1085 
1086  /*---------------------------------------------------------------
1087  * get flags
1088  *---------------------------------------------------------------*/
1089  int flags = 0;
1090  if (stemSource != NULLOBJECT)
1091  {
1092  if (!stem.resolveStem(stemSource))
1093  {
1094  return 0;
1095  }
1096 
1097  char *flagStr = strdup(context->ObjectToStringValue(flagsOrStem));
1098  if (flagStr == NULL)
1099  {
1100  context->InvalidRoutine();
1101  return 0;
1102  }
1103 
1104  const char *pszWord = strtok(flagStr, " ");
1105  while (pszWord)
1106  {
1107  if (!caselessCompare(pszWord,"MSG_DONTROUTE"))
1108  {
1109  flags |= MSG_DONTROUTE;
1110  }
1111  pszWord = strtok(NULL," ");
1112  }
1113 
1114  }
1115  else
1116  {
1117  if (!stem.resolveStem(flagsOrStem))
1118  {
1119  return 0;
1120  }
1121  }
1122 
1123  stemToSockAddr(context, stem, &addr);
1124 
1125  /*---------------------------------------------------------------
1126  * call function
1127  *---------------------------------------------------------------*/
1128  int rc = sendto(sock,data,dataLen,flags,(struct sockaddr *)&addr,sizeof(addr));
1129 
1130  // set the errno information
1131  cleanup(context);
1132 
1133  /*---------------------------------------------------------------
1134  * set return code
1135  *---------------------------------------------------------------*/
1136  return rc;
1137 }
1138 
1139 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1140 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1141 /*------------------------------------------------------------------
1142  * setsockopt()
1143  *------------------------------------------------------------------*/
1144 RexxRoutine4(int, SockSetSockOpt, int, sock, CSTRING, target, CSTRING, option, CSTRING, arg)
1145 {
1146  struct linger lingStruct;
1147  int intVal;
1148  int intVal2;
1149  socklen_t lenVal;
1150  int len;
1151  void *ptr;
1152 
1153 
1154  if (caselessCompare("SOL_SOCKET", target))
1155  {
1156  context->InvalidRoutine();
1157  return 0;
1158  }
1159 
1160  /*---------------------------------------------------------------
1161  * get option name
1162  *---------------------------------------------------------------*/
1163  int opt = stringToSockOpt(option);
1164 
1165  /*---------------------------------------------------------------
1166  * get option value
1167  *---------------------------------------------------------------*/
1168  switch (opt)
1169  {
1170  default:
1171  ptr = &intVal;
1172  len = sizeof(int);
1173  sscanf(arg, "%d", &intVal);
1174  break;
1175 
1176  case SO_LINGER:
1177  ptr = &lingStruct;
1178  len = sizeof(lingStruct);
1179 
1180  sscanf(arg,"%d %d", &intVal,&intVal2);
1181  lingStruct.l_onoff = (u_short)intVal;
1182  lingStruct.l_linger = (u_short)intVal2;
1183 
1184  break;
1185 
1186  case SO_RCVBUF:
1187  case SO_SNDBUF:
1188  ptr = &lenVal;
1189  len = sizeof(lenVal);
1190 
1191  sscanf(arg, "%d", &lenVal);
1192  break;
1193 
1194  case SO_ERROR:
1195  case SO_TYPE:
1196  return -1;
1197  }
1198 
1199  /*---------------------------------------------------------------
1200  * make call
1201  *---------------------------------------------------------------*/
1202  int rc = setsockopt(sock,SOL_SOCKET,opt,(const char *)ptr,len);
1203 
1204  // set the errno information
1205  cleanup(context);
1206 
1207  /*---------------------------------------------------------------
1208  * set return code
1209  *---------------------------------------------------------------*/
1210  return rc;
1211 }
1212 
1213 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1214 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1215 
1216 /*------------------------------------------------------------------
1217  * shutdown()
1218  *------------------------------------------------------------------*/
1219 RexxRoutine2(int, SockShutDown, int, sock, int, how)
1220 {
1221  /*---------------------------------------------------------------
1222  * call function
1223  *---------------------------------------------------------------*/
1224  int rc = shutdown(sock, how);
1225 
1226  // set the errno information
1227  cleanup(context);
1228 
1229  /*---------------------------------------------------------------
1230  * set return code
1231  *---------------------------------------------------------------*/
1232  return rc;
1233 }
1234 
1235 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1236 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1237 
1238 /*------------------------------------------------------------------
1239  * sock_init()
1240  *------------------------------------------------------------------*/
1241 RexxRoutine0(int, SockInit)
1242 {
1243 #ifdef WIN32
1244  WORD wVersionRequested;
1245  WSADATA wsaData;
1246  wVersionRequested = MAKEWORD( 1, 1 );
1247  int rc = WSAStartup( wVersionRequested, &wsaData );
1248 #else
1249  int rc = 0;
1250 #endif
1251  // set the errno information
1252  cleanup(context);
1253 
1254  /*---------------------------------------------------------------
1255  * set return code
1256  *---------------------------------------------------------------*/
1257  return rc;
1258 }
1259 
1260 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1261 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1262 
1263 /*------------------------------------------------------------------
1264  * socket()
1265  *------------------------------------------------------------------*/
1266 RexxRoutine3(int, SockSocket, CSTRING, domainArg, CSTRING, typeArg, CSTRING, protocolArg)
1267 {
1268  int domain;
1269  int type;
1270  int protocol;
1271  char *pszDomain;
1272  char *pszType;
1273  char *pszProtocol;
1274 
1275  /*---------------------------------------------------------------
1276  * get parms
1277  *---------------------------------------------------------------*/
1278  pszDomain = strdup(domainArg);
1279  pszType = strdup(typeArg);
1280  pszProtocol = strdup(protocolArg);
1281 
1282  stripBlanks(pszDomain);
1283  stripBlanks(pszType);
1284  stripBlanks(pszProtocol);
1285 
1286  if (!caselessCompare(pszDomain,"AF_INET"))
1287  {
1288  domain = AF_INET;
1289  }
1290  else
1291  {
1292  context->InvalidRoutine();
1293  return 0;
1294  }
1295 
1296  if (!caselessCompare(pszType,"SOCK_STREAM")) type = SOCK_STREAM;
1297  else if (!caselessCompare(pszType,"SOCK_DGRAM" )) type = SOCK_DGRAM;
1298  else if (!caselessCompare(pszType,"SOCK_RAW" )) type = SOCK_RAW;
1299  else
1300  {
1301  context->InvalidRoutine();
1302  return 0;
1303  }
1304 
1305  if (!caselessCompare(pszProtocol,"IPPROTO_UDP"))
1306  protocol = IPPROTO_UDP;
1307  else if (!caselessCompare(pszProtocol,"IPPROTO_TCP"))
1308  protocol = IPPROTO_TCP;
1309  else if (!caselessCompare(pszProtocol,"0" ))
1310  protocol = 0;
1311  else
1312  {
1313  context->InvalidRoutine();
1314  return 0;
1315  }
1316 
1317  /*---------------------------------------------------------------
1318  * call function
1319  *---------------------------------------------------------------*/
1320  int rc = socket(domain,type,protocol);
1321  // set the errno information
1322  cleanup(context);
1323 
1324  /*---------------------------------------------------------------
1325  * set return code
1326  *---------------------------------------------------------------*/
1327  return rc;
1328 }
1329 
1330 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
1331 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
1332 
1333 /*------------------------------------------------------------------
1334  * soclose()
1335  *------------------------------------------------------------------*/
1336 RexxRoutine1(int, SockSoClose, int, sock)
1337 {
1338  /*---------------------------------------------------------------
1339  * call function
1340  *---------------------------------------------------------------*/
1341 #if defined(WIN32)
1342  int rc = closesocket(sock);
1343 #else
1344  int rc = close(sock);
1345 #endif
1346  // set the errno information
1347  cleanup(context);
1348  return rc;
1349 }
1350 
bool resolveStem(RexxObjectPtr source)
Definition: rxsock.h:134
int type
Definition: cmdparse.cpp:383
#define argumentOmitted(i)
Definition: oorexxapi.h:3778
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
void intArrayToStem(RexxCallContext *context, RexxObjectPtr stem, int count, int *arr)
Definition: rxsock.cpp:232
void stemToIntArray(RexxCallContext *context, RexxObjectPtr stem, int &count, int *&arr)
Definition: rxsock.cpp:173
struct sockaddr_in sockaddr_in
Definition: rxsock.h:48
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
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 cleanup(RexxCallContext *context)
Definition: rxsock.cpp:584
void stripBlanks(char *string)
Definition: rxsock.cpp:124
struct in_addr in_addr
Definition: rxsock.h:49
RexxRoutine0(int, SockSock_Errno)
Definition: rxsockfn.cpp:106
RexxRoutine2(int, SockAccept, int, sock, OPTIONAL_RexxObjectPtr, stemSource)
Definition: rxsockfn.cpp:142
RexxRoutine4(int, SockGetSockOpt, int, sock, CSTRING, level, CSTRING, option, CSTRING, var)
Definition: rxsockfn.cpp:499
RexxRoutine5(int, SockRecvFrom, int, sock, CSTRING, var, int, dataLen, RexxObjectPtr, flagArg, OPTIONAL_RexxObjectPtr, stemSource)
Definition: rxsockfn.cpp:729
#define psock_errno(s)
Definition: rxsockfn.cpp:84
#define sock_errno()
Definition: rxsockfn.cpp:89
RexxRoutine1(CSTRING, SockPSock_Errno, OPTIONAL_CSTRING, type)
Definition: rxsockfn.cpp:118
RexxRoutine3(int, SockGetHostByAddr, CSTRING, addrArg, RexxObjectPtr, stemSource, OPTIONAL_int, domain)
Definition: rxsockfn.cpp:263
int int32_t
unsigned int uint32_t