home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / CLISP / CLISPSRC.TAR / clisp-1995-01-01 / src / socket.d < prev    next >
Encoding:
Text File  |  1994-06-19  |  11.6 KB  |  340 lines

  1. # Setting up a connection to an X server
  2. # Bruno Haible 19.6.1994
  3.  
  4. # This code comes from the X11R5 distribution, file mit/X/XConnDis.c,
  5. # with the following modifications:
  6. # - no support for DNETCONN or STREAMSCONN,
  7. # - display name has already been split into hostname and display number,
  8. # - doesn't return full host&display name and auth info,
  9. # - doesn't depend on the X include files.
  10.  
  11. # mit/X/XConnDis.c carries the following copyright notice:
  12. /*
  13.  * $XConsortium: XConnDis.c,v 11.85 91/07/19 23:07:39 gildea Exp $
  14.  *
  15.  * Copyright 1989 Massachusetts Institute of Technology
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appear in all copies and that both that
  20.  * copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of M.I.T. not be used in advertising
  22.  * or publicity pertaining to distribution of the software without specific,
  23.  * written prior permission.  M.I.T. makes no representations about the
  24.  * suitability of this software for any purpose.  It is provided "as is"
  25.  * without express or implied warranty.
  26.  *
  27.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  29.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  30.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  31.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  32.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  *
  35.  * This file contains operating system dependencies.
  36.  */
  37.  
  38. # These are the only things we need from lispbibl.c :
  39. #include "unixconf.h"
  40. #define global
  41. #define var
  42.  
  43. # We assume that if we have gethostbyname(), we have a networking Unix.
  44. # and have either UNIX domain connections or TCP/IP connections.
  45. #ifdef HAVE_GETHOSTBYNAME
  46.  
  47. #ifdef HAVE_SYS_UN_H  # have <sys/un.h> and Unix domain sockets?
  48.   #define UNIXCONN  # use Unix domain sockets
  49. #endif
  50. #ifdef HAVE_NETINET_IN_H  # have <netinet/in.h> ?
  51.   #define TCPCONN  # use TCP/IP sockets
  52. #endif
  53.  
  54. #include <sys/types.h>
  55. #ifdef HAVE_UNISTD_H
  56. #include <unistd.h> # declares fcntl(), close(), sleep()
  57. #endif
  58.  
  59. #include <errno.h>
  60. extern int errno;
  61. #ifndef ENOSYS
  62.   #define ENOSYS  EINVAL
  63. #endif
  64.  
  65. #include <fcntl.h> # declares fcntl() and defines F_SETFD
  66. #ifdef FCNTL_DOTS
  67.   extern int fcntl (int fd, int cmd, ...);
  68. #else
  69.   extern int fcntl (int fd, int cmd, int arg);
  70. #endif
  71. #ifndef FD_CLOEXEC
  72.   #define FD_CLOEXEC  1
  73. #endif
  74.  
  75. extern int close (int fd);
  76. #define CLOSE(fd)  while ((close(fd) < 0) && (errno == EINTR)) ;
  77.  
  78. #if defined(UNIXCONN) || defined(TCPCONN)
  79.  
  80. # include <sys/types.h>
  81. #include <sys/socket.h> # declares socket(), connect(), defines AF_UNIX, AF_INET
  82. extern int socket (int domain, int type, int protocol);
  83. extern int connect (int fd, CONNECT_CONST CONNECT_NAME_T name, int namelen);
  84.  
  85. # A wrapper around the connect() function.
  86.   global int nonintr_connect (int fd, struct sockaddr * name, int namelen);
  87.   global int nonintr_connect(fd,name,namelen)
  88.     var int fd;
  89.     var struct sockaddr * name;
  90.     var int namelen;
  91.     { var int retval;
  92.       do { retval = connect(fd,name,namelen); }
  93.          while ((retval < 0) && (errno == EINTR));
  94.       return retval;
  95.     }
  96.   #define connect nonintr_connect
  97.  
  98. extern unsigned int sleep (unsigned int seconds);
  99.  
  100. #endif
  101.  
  102. #ifdef UNIXCONN
  103.   #include <stdio.h>   # declares sprintf()
  104.   #include <string.h>  # declares strcmp(), strlen()
  105.   #ifdef RETSTRLENTYPE /* unless strlen() is a macro */
  106.     extern RETSTRLENTYPE strlen (STRLEN_CONST char* s);
  107.   #endif
  108.   #include <sys/un.h>  # defines struct sockaddr_un
  109.   # set X_UNIX_PATH and - on hpux only - OLD_UNIX_PATH
  110.   #ifndef X_UNIX_PATH
  111.     #ifndef hpux
  112.       #define X_UNIX_PATH "/tmp/.X11-unix/X"
  113.     #else
  114.       #define X_UNIX_PATH "/usr/spool/sockets/X11/"
  115.       #define OLD_UNIX_PATH "/tmp/.X11-unix/X"
  116.     #endif
  117.   #endif
  118. #endif
  119.  
  120. #ifdef TCPCONN
  121.   #ifdef HAVE_GETHOSTNAME
  122.     extern int gethostname (char* name, GETHOSTNAME_SIZE_T namelen);
  123.   #endif
  124.   #ifdef HAVE_SYS_UTSNAME_H
  125.     #include <sys/utsname.h>
  126.     extern int uname (struct utsname * buf);
  127.   #endif
  128.   #ifdef HAVE_GETHOSTBYNAME
  129.     #include <sys/types.h>
  130.     #ifdef HAVE_NETDB_H
  131.       # include <sys/socket.h>
  132.       #include <netdb.h>
  133.     #else
  134.       #include <sun/netdb.h>
  135.     #endif
  136.     extern struct hostent * gethostbyname (GETHOSTBYNAME_CONST char* name);
  137.   #endif
  138.   #ifndef MAXHOSTNAMELEN
  139.     #define MAXHOSTNAMELEN 64
  140.   #endif
  141.   #include <netinet/in.h> # declares htons(), defines struct sockaddr_in
  142.   #ifdef HAVE_ARPA_INET_H
  143.     #include <arpa/inet.h> # declares inet_addr()
  144.   #endif
  145.   extern RET_INET_ADDR_TYPE inet_addr (INET_ADDR_CONST char* host);
  146.   #ifdef HAVE_NETINET_TCP_H
  147.     #if defined(__386BSD__) || defined(__NetBSD__)
  148.       #include <machine/endian.h> # needed for <netinet/tcp.h>
  149.     #endif
  150.     #include <netinet/tcp.h> # declares TCP_NODELAY
  151.   #endif
  152.   extern int setsockopt (/* int fd, int level, int optname, char* optval, int optlen */);
  153.   #define X_TCP_PORT  6000  # from <X11/Xproto.h>
  154. #endif
  155.  
  156. # Attempts to connect to server, given host name and display number.
  157. # Returns file descriptor (network socket). Returns -1 and sets errbo
  158. # if connection fails.
  159. # An empty hostname is interpreted as the most efficient local connection to
  160. # a server on the same machine (usually a UNIX domain socket).
  161. # hostname="unix" is interpreted as a UNIX domain connection.
  162.  
  163. global int connect_to_server (char* host, int display);
  164. global int connect_to_server(host,display)
  165.   var char* host;  # host of display
  166.   var int display; # display number (screen number always zero)
  167. { var int fd;      # file descriptor to return
  168.   var int retries = 3; # number of retries on ECONNREFUSED
  169.  
  170.   var int conntype; # type of desired connection
  171.   #define conn_none 0
  172.   #define conn_unix 1
  173.   #define conn_tcp  2
  174.   #ifdef TCPCONN
  175.     conntype = conn_tcp;
  176.   #else
  177.     conntype = conn_none;
  178.   #endif
  179.   #ifdef UNIXCONN
  180.     if (host[0] == '\0')
  181.       {
  182.         #ifndef apollo # Unix domain sockets are *really* bad on apollos
  183.         conntype = conn_unix;
  184.         #endif
  185.       }
  186.     else if (strcmp(host,"unix")==0)
  187.       { conntype = conn_unix; }
  188.   #endif
  189.  
  190.   # Make the connection. Do retries in case server host has hit its
  191.   # backlog (which, unfortunately, isn't distinguishable from there not
  192.   # being a server listening at all, which is why we have to not retry
  193.   # too many times).
  194.  
  195.   #ifdef UNIXCONN
  196.   if (conntype == conn_unix)
  197.     {
  198.       var struct sockaddr_un unaddr;          # UNIX socket data block
  199.       var struct sockaddr * addr;             # generic socket pointer
  200.       var int addrlen;                        # length of addr
  201.       #ifdef hpux /* this is disgusting */
  202.       var struct sockaddr_un ounaddr;         # UNIX socket data block
  203.       var struct sockaddr * oaddr;            # generic socket pointer
  204.       var int oaddrlen;                       # length of addr
  205.       #endif
  206.  
  207.       unaddr.sun_family = AF_UNIX;
  208.       sprintf (unaddr.sun_path, "%s%d", X_UNIX_PATH, display);
  209.       addr = (struct sockaddr *) &unaddr;
  210.       #ifdef HAVE_SOCKADDR_UN_LEN /* this is AIX */
  211.       unaddr.sun_len = strlen(unaddr.sun_path); addrlen = sizeof(unaddr);
  212.       #else
  213.       addrlen = strlen(unaddr.sun_path) + sizeof(unaddr.sun_family);
  214.       #endif
  215.       #ifdef hpux /* this is disgusting */
  216.       ounaddr.sun_family = AF_UNIX;
  217.       sprintf (ounaddr.sun_path, "%s%d", OLD_UNIX_PATH, display);
  218.       oaddr = (struct sockaddr *) &ounaddr;
  219.       #ifdef HAVE_SOCKADDR_UN_LEN /* this is AIX */
  220.       ounaddr.sun_len = strlen(ounaddr.sun_path); oaddrlen = sizeof(ounaddr);
  221.       #else
  222.       oaddrlen = strlen(ounaddr.sun_path) + sizeof(ounaddr.sun_family);
  223.       #endif
  224.       #endif
  225.  
  226.       # Open the network connection.
  227.       do { if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) >= 0)
  228.              { if (connect (fd, addr, addrlen) >= 0)
  229.                  break;
  230.                  else
  231.                  { int olderrno = errno; CLOSE(fd); errno = olderrno; }
  232.              }
  233.            #ifdef hpux /* this is disgusting */
  234.            if (errno == ENOENT)
  235.              { if ((fd = socket((int) oaddr->sa_family, SOCK_STREAM, 0)) >= 0)
  236.                  { if (connect (fd, oaddr, oaddrlen) >= 0)
  237.                      break;
  238.                      else
  239.                      { int olderrno = errno; CLOSE(fd); errno = olderrno; }
  240.              }   }
  241.            #endif
  242.            if (!((errno == ENOENT) && (retries > 0)))
  243.              { return -1; }
  244.            sleep (1);
  245.          }
  246.          while (retries-- > 0);
  247.     }
  248.   else
  249.   #endif
  250.  
  251.   #ifdef TCPCONN
  252.   if (conntype == conn_tcp)
  253.     {
  254.       #if defined(HAVE_GETHOSTNAME)
  255.       var char hostname[MAXHOSTNAMELEN+1];
  256.       #elif defined(HAVE_SYS_UTSNAME_H)
  257.       var struct utsname utsname;
  258.       #endif
  259.       var unsigned long hostinetaddr;       # result of inet_addr of arpa addr
  260.       var struct sockaddr_in inaddr;        # IP socket
  261.       var struct sockaddr * addr;           # generic socket pointer
  262.       var int addrlen;                      # length of addr
  263.       if (host[0] == '\0')
  264.         { # get host name
  265.           #if defined(HAVE_GETHOSTNAME)
  266.           if (gethostname(&!hostname,MAXHOSTNAMELEN) < 0) { return -1; }
  267.           hostname[MAXHOSTNAMELEN] = '\0';
  268.           host = &!hostname;
  269.           #elif defined(HAVE_SYS_UTSNAME_H)
  270.           if (uname(&utsname) < 0) { return -1; }
  271.           host = &!utsname.nodename;
  272.           #else
  273.           ??
  274.           #endif
  275.         }
  276.       # if numeric host name then try to parse it as such; do the number
  277.       # first because some systems return garbage instead of INVALID_INETADDR
  278.       #define INVALID_INETADDR  ((unsigned long) -1)
  279.       if ((host[0] >= '0') && (host[0] <= '9'))
  280.         { hostinetaddr = inet_addr(host) INET_ADDR_SUFFIX ; }
  281.         else
  282.         { hostinetaddr = INVALID_INETADDR; }
  283.       # try numeric
  284.       if (hostinetaddr == INVALID_INETADDR)
  285.         { var struct hostent * host_ptr; # entry in hosts table
  286.           if ((host_ptr = gethostbyname(host)) == NULL)
  287.             { errno = EINVAL; return -1; } # No such host!
  288.           # Check the address type for an internet host.
  289.           if (host_ptr->h_addrtype != AF_INET)
  290.             { errno = EPROTOTYPE; return -1; } # Not an Internet host!
  291.           # Set up the socket data.
  292.           inaddr.sin_family = host_ptr->h_addrtype;
  293.           inaddr.sin_addr = *(struct in_addr *)host_ptr->h_addr;
  294.         }
  295.         else
  296.         { inaddr.sin_family = AF_INET;
  297.           inaddr.sin_addr.s_addr = hostinetaddr;
  298.         }
  299.  
  300.       inaddr.sin_port = X_TCP_PORT + display;
  301.       inaddr.sin_port = htons(inaddr.sin_port);
  302.       addr = (struct sockaddr *) &inaddr;
  303.       addrlen = sizeof(struct sockaddr_in);
  304.  
  305.       # Open the network connection.
  306.       do { if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0)
  307.              { return -1; }
  308.            #ifdef TCP_NODELAY
  309.            # turn off TCP coalescence
  310.            { int tmp = 1;
  311.              setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tmp, sizeof(int));
  312.            }
  313.            #endif
  314.            # Connect to the socket.
  315.            # If there is no X server or if the backlog has been reached,
  316.            # then ECONNREFUSED will be returned.
  317.            if (connect (fd, addr, addrlen) >= 0)
  318.              break;
  319.            { int olderrno = errno; CLOSE(fd); errno = olderrno; }
  320.            if (!((errno == ECONNREFUSED) && (retries > 0)))
  321.              { return -1; }
  322.            sleep (1);
  323.          }
  324.          while (retries-- > 0);
  325.     }
  326.   else
  327.   #endif
  328.  
  329.   # (conntype == conn_none)
  330.     { errno = ENOSYS; return -1; }
  331.  
  332.   # Set close-on-exec so that we won't get confused if we fork().
  333.   fcntl(fd,F_SETFD,FD_CLOEXEC);
  334.  
  335.   return fd;
  336. }
  337.  
  338. #endif # HAVE_GETHOSTBYNAME
  339.  
  340.