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