home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / uxsock.c < prev    next >
C/C++ Source or Header  |  2001-06-01  |  8KB  |  312 lines

  1. /* -*-C-*-
  2.  
  3. $Id: uxsock.c,v 1.28 2001/06/02 01:21:58 cph Exp $
  4.  
  5. Copyright (c) 1990-2001 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  20. USA.
  21. */
  22.  
  23. #include "ux.h"
  24. #include "osio.h"
  25.  
  26. #ifdef HAVE_SOCKETS
  27.  
  28. #include "uxsock.h"
  29. #include "uxio.h"
  30. #include "prims.h"
  31. #include "limits.h"
  32.  
  33. static void do_connect (int, struct sockaddr *, socklen_t);
  34.  
  35. Tchannel
  36. DEFUN (OS_open_tcp_stream_socket, (host, port),
  37.        PTR host AND
  38.        unsigned int port)
  39. {
  40.   int s;
  41.   Tchannel channel;
  42.  
  43.   transaction_begin ();
  44.   STD_UINT_SYSTEM_CALL
  45.     (syscall_socket, s, (UX_socket (AF_INET, SOCK_STREAM, 0)));
  46.   MAKE_CHANNEL (s, channel_type_tcp_stream_socket, channel =);
  47.   OS_channel_close_on_abort (channel);
  48.   {
  49.     struct sockaddr_in address;
  50.     (address . sin_family) = AF_INET;
  51.     memcpy ((& (address . sin_addr)), host, (sizeof (address . sin_addr)));
  52.     (address . sin_port) = port;
  53.     do_connect (s, ((struct sockaddr *) (&address)), (sizeof (address)));
  54.   }
  55.   transaction_commit ();
  56.   return (channel);
  57. }
  58.  
  59. static void
  60. do_connect (int s, struct sockaddr * address, socklen_t addr_len)
  61. {
  62.   if ((UX_connect (s, address, addr_len)) < 0)
  63.     {
  64.       if (errno != EINTR)
  65.     error_system_call (errno, syscall_connect);
  66.       while (1)
  67.     {
  68.       deliver_pending_interrupts ();
  69.       /* Yuk; lots of hair because connect can't be restarted.
  70.          Instead, we must wait for the connection to finish, then
  71.          examine the SO_ERROR socket option.  */
  72. #ifdef HAVE_POLL
  73.       {
  74.         struct pollfd fds;
  75.         int nfds;
  76.  
  77.         (fds . fd) = s;
  78.         (fds . events) = (POLLIN | POLLOUT);
  79.         nfds = (poll ((&fds), 1, 0));
  80.         if ((nfds > 0) && (((fds . revents) & (POLLIN | POLLOUT)) != 0))
  81.           break;
  82.         if ((nfds < 0) && (errno != EINTR))
  83.           error_system_call (errno, syscall_select);
  84.       }
  85. #else /* not HAVE_POLL */
  86. #ifdef HAVE_SELECT
  87.       {
  88.         fd_set readers;
  89.         fd_set writers;
  90.         int result;
  91.  
  92.         FD_ZERO (&readers);
  93.         FD_SET (s, (&readers));
  94.         writers = readers;
  95.         result = (UX_select ((s + 1), (&readers), (&writers), 0, 0));
  96.         if ((result > 0)
  97.         && ((FD_ISSET (s, (&readers))) || (FD_ISSET (s, (&writers)))))
  98.           break;
  99.         if ((result < 0) && (errno != EINTR))
  100.           error_system_call (errno, syscall_select);
  101.       }
  102. #else /* not HAVE_SELECT */
  103.       error_system_call (errno, syscall_connect);
  104.       break;
  105. #endif /* not HAVE_SELECT */
  106. #endif /* not HAVE_POLL */
  107.     }
  108.       {
  109.     int error;
  110.     socklen_t len = (sizeof (error));
  111.     if (((getsockopt (s, SOL_SOCKET, SO_ERROR, (&error), (&len))) < 0)
  112.         || (error != 0))
  113.       error_system_call (error, syscall_connect);
  114.       }
  115.     }
  116. }
  117.  
  118. int
  119. DEFUN (OS_get_service_by_name, (service_name, protocol_name),
  120.        CONST char * service_name AND
  121.        CONST char * protocol_name)
  122. {
  123.   struct servent * entry = (UX_getservbyname (service_name, protocol_name));
  124.   return ((entry == 0) ? (-1) : (entry -> s_port));
  125. }
  126.  
  127. unsigned long
  128. DEFUN (OS_get_service_by_number, (port_number),
  129.        CONST unsigned long port_number)
  130. {
  131.   return ((unsigned long) (htons ((unsigned short) port_number)));
  132. }
  133.  
  134. unsigned int
  135. DEFUN_VOID (OS_host_address_length)
  136. {
  137.   return (sizeof (struct in_addr));
  138. }
  139.  
  140. char **
  141. DEFUN (OS_get_host_by_name, (host_name), CONST char * host_name)
  142. {
  143.   struct hostent * entry = (UX_gethostbyname (host_name));
  144.   if (entry == 0)
  145.     return (0);
  146. #ifdef HAVE_HOSTENT_H_ADDR_LIST
  147.   return (entry -> h_addr_list);
  148. #else
  149.   {
  150.     static char * addresses [2];
  151.     (addresses[0]) = (entry -> h_addr);
  152.     (addresses[1]) = 0;
  153.     return (addresses);
  154.   }
  155. #endif
  156. }
  157.  
  158. #define HOSTNAMESIZE 1024
  159.  
  160. CONST char *
  161. DEFUN_VOID (OS_get_host_name)
  162. {
  163.   char host_name [HOSTNAMESIZE];
  164.   STD_VOID_SYSTEM_CALL
  165.     (syscall_gethostname, (UX_gethostname (host_name, HOSTNAMESIZE)));
  166.   {
  167.     char * result = (OS_malloc ((strlen (host_name)) + 1));
  168.     strcpy (result, host_name);
  169.     return (result);
  170.   }
  171. }
  172.  
  173. CONST char *
  174. DEFUN (OS_canonical_host_name, (host_name), CONST char * host_name)
  175. {
  176.   struct hostent * entry = (gethostbyname (host_name));
  177.   if (entry == 0)
  178.     return (0);
  179.   {
  180.     char * result = (OS_malloc ((strlen (entry -> h_name)) + 1));
  181.     strcpy (result, (entry -> h_name));
  182.     return (result);
  183.   }
  184. }
  185.  
  186. CONST char *
  187. DEFUN (OS_get_host_by_address, (host_addr), CONST char * host_addr)
  188. {
  189.   struct hostent * entry
  190.     = (gethostbyaddr (host_addr, (OS_host_address_length ()), AF_INET));
  191.   if (entry == 0)
  192.     return (0);
  193.   {
  194.     char * result = (OS_malloc ((strlen (entry -> h_name)) + 1));
  195.     strcpy (result, (entry -> h_name));
  196.     return (result);
  197.   }
  198. }
  199.  
  200. void
  201. DEFUN (OS_host_address_any, (addr), PTR addr)
  202. {
  203.   (((struct in_addr *) addr) -> s_addr) = (htonl (INADDR_ANY));
  204. }
  205.  
  206. void
  207. DEFUN (OS_host_address_loopback, (addr), PTR addr)
  208. {
  209.   (((struct in_addr *) addr) -> s_addr) = (htonl (INADDR_LOOPBACK));
  210. }
  211.  
  212. #ifdef HAVE_UNIX_SOCKETS
  213. Tchannel
  214. DEFUN (OS_open_unix_stream_socket, (filename), CONST char * filename)
  215. {
  216.   int s;
  217.   Tchannel channel;
  218.  
  219.   transaction_begin ();
  220.   STD_UINT_SYSTEM_CALL
  221.     (syscall_socket, s, (UX_socket (AF_UNIX, SOCK_STREAM, 0)));
  222.   MAKE_CHANNEL (s, channel_type_unix_stream_socket, channel =);
  223.   OS_channel_close_on_abort (channel);
  224.   {
  225.     struct sockaddr_un address;
  226.     (address . sun_family) = AF_UNIX;
  227.     strncpy ((address . sun_path), filename, (sizeof (address . sun_path)));
  228.     do_connect (s, ((struct sockaddr *) (&address)), (sizeof (address)));
  229.   }
  230.   transaction_commit ();
  231.   return (channel);
  232. }
  233. #endif /* HAVE_UNIX_SOCKETS */
  234.  
  235. Tchannel
  236. DEFUN_VOID (OS_create_tcp_server_socket)
  237. {
  238.   int s;
  239.   STD_UINT_SYSTEM_CALL
  240.     (syscall_socket, s, (UX_socket (AF_INET, SOCK_STREAM, 0)));
  241.   MAKE_CHANNEL (s, channel_type_tcp_server_socket, return);
  242. }
  243.  
  244. void
  245. DEFUN (OS_bind_tcp_server_socket, (channel, host, port),
  246.        Tchannel channel AND
  247.        PTR host AND
  248.        unsigned int port)
  249. {
  250.   struct sockaddr_in address;
  251.   (address . sin_family) = AF_INET;
  252.   memcpy ((& (address . sin_addr)), host, (sizeof (address . sin_addr)));
  253.   (address . sin_port) = port;
  254.   STD_VOID_SYSTEM_CALL
  255.     (syscall_bind, (UX_bind ((CHANNEL_DESCRIPTOR (channel)),
  256.                  ((struct sockaddr *) (&address)),
  257.                  (sizeof (struct sockaddr_in)))));
  258. }
  259.  
  260. #ifndef SOCKET_LISTEN_BACKLOG
  261. #define SOCKET_LISTEN_BACKLOG 1024
  262. #endif
  263.  
  264. void
  265. DEFUN (OS_listen_tcp_server_socket, (channel), Tchannel channel)
  266. {
  267.   STD_VOID_SYSTEM_CALL
  268.     (syscall_listen,
  269.      (UX_listen ((CHANNEL_DESCRIPTOR (channel)), SOCKET_LISTEN_BACKLOG)));
  270. }
  271.  
  272. Tchannel
  273. DEFUN (OS_server_connection_accept, (channel, peer_host, peer_port),
  274.        Tchannel channel AND
  275.        PTR peer_host AND
  276.        unsigned int * peer_port)
  277. {
  278.   static struct sockaddr_in address;
  279.   int address_length = (sizeof (struct sockaddr_in));
  280.   int s;
  281.   while (1)
  282.     {
  283.       s = (UX_accept ((CHANNEL_DESCRIPTOR (channel)),
  284.               ((struct sockaddr *) (&address)),
  285.               (&address_length)));
  286.       if (s >= 0)
  287.     break;
  288.       if (errno != EINTR)
  289.     {
  290. #ifdef EAGAIN
  291.       if (errno == EAGAIN)
  292.         return (NO_CHANNEL);
  293. #endif
  294. #ifdef EWOULDBLOCK
  295.       if (errno == EWOULDBLOCK)
  296.         return (NO_CHANNEL);
  297. #endif
  298.       error_system_call (errno, syscall_accept);
  299.     }
  300.       deliver_pending_interrupts ();
  301.     }
  302.   if (peer_host != 0)
  303.     memcpy (peer_host,
  304.         (& (address . sin_addr)),
  305.         (sizeof (address . sin_addr)));
  306.   if (peer_port != 0)
  307.     (*peer_port) = (address . sin_port);
  308.   MAKE_CHANNEL (s, channel_type_tcp_stream_socket, return);
  309. }
  310.  
  311. #endif /* not HAVE_SOCKETS */
  312.