ftp.nice.ch/pub/next/developer/languages/smalltalk/smalltalk.1.2.alpha5.s.tar.gz#/smalltalk-1.2.alpha5/stix/socket.c

This is socket.c in view mode; [Download] [Up]

/* Copyright    Massachusetts Institute of Technology    1988	*/
/*
 * THIS IS AN OS DEPENDENT FILE! It should work on 4.2BSD derived
 * systems.  VMS and System V should plan to have their own version.
 *
 * This code was cribbed from lib/X/XConnDis.c.
 * Compile using   
 *                    % cc -c socket.c -DUNIXCONN
 *
 *    Change Log
 * ============================================================================
 * Author      Date       Change 
 * sbb	     15 Sep 95	  More hacks to get around cruft of HP-UX (missing
 *			  getdtablesize). 
 *
 * sbb	      6 Jun 95	  Switched to new file naming scheme.
 *
 * sbb	      7 May 95	  Altered the FD_SET usage -- the code now guesses that
 *			  if the FD_SET macro is defined the fd_set datatype
 *			  will be too.
 *
 */

#include <stdio.h>
#ifndef COMPILE_ONLY
#include <X11/Xos.h>
#include <X11/Xproto.h>
#else
#include <sys/types.h>
#endif
#include <errno.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <netdb.h> 
#include <sys/socket.h>
#ifndef hpux /* ??? what should  we do on HPUX? */
# if defined(LITTLE_ENDIAN)
#  undef LITTLE_ENDIAN		/* remove warnings on some Linuxes */
# endif
# include <netinet/tcp.h>
# include <arpa/inet.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include "gst.h"
#include "gstpub.h"

#if !defined(HAVE_GETDTABLESIZE)
# include "sysdep.h"		/* only for getdtablesize */
#endif

static int connect_to_server();
static int waitForSocket();

extern int errno;		/* Certain (broken) OS's don't have this */
				/* decl in errno.h */

#ifdef UNIXCONN
#include <sys/un.h>
#ifndef X_UNIX_PATH
#define X_UNIX_PATH "/tmp/.X11-unix/X"
#endif /* X_UNIX_PATH */
#endif /* UNIXCONN */
void bcopy();

void defineSocket()
{
  defineCFunc("connectToServer", connect_to_server);
  defineCFunc("waitForSocket", waitForSocket);
}


/* 
 * Attempts to connect to server, given host and display. Returns file 
 * descriptor (network socket) or 0 if connection fails.
 */

static int connect_to_server (host, display)
     char *host;
     int display;
{
  struct sockaddr_in inaddr;	/* INET socket address. */
  struct sockaddr *addr;		/* address to connect to */
  struct hostent *host_ptr;
  int addrlen;			/* length of address */
#ifdef UNIXCONN
  struct sockaddr_un unaddr;	/* UNIX socket address. */
#endif
  extern char *getenv();
  extern struct hostent *gethostbyname();
  int fd;				/* Network socket */

#ifndef COMPILE_ONLY
  {
#ifdef UNIXCONN
    if ((host[0] == '\0') || 
	(strcmp("unix", host) == 0)) {
	/* Connect locally using Unix domain. */
	unaddr.sun_family = AF_UNIX;
	(void) strcpy(unaddr.sun_path, X_UNIX_PATH);
	sprintf(&unaddr.sun_path[strlen(unaddr.sun_path)], "%d", display);
	addr = (struct sockaddr *) &unaddr;
	addrlen = strlen(unaddr.sun_path) + 2;
	/*
	 * Open the network connection.
	 */
	if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0)
	    return(-1);	    /* errno set by system call. */
    } else
#endif
    {
      /* Get the statistics on the specified host. */
      if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1) 
	{
	  if ((host_ptr = gethostbyname(host)) == NULL) 
	    {
	      /* No such host! */
	      errno = EINVAL;
	      return(-1);
	    }
	  /* Check the address type for an internet host. */
	  if (host_ptr->h_addrtype != AF_INET) 
	    {
	      /* Not an Internet host! */
	      errno = EPROTOTYPE;
	      return(-1);
	    }
	  /* Set up the socket data. */
	  inaddr.sin_family = host_ptr->h_addrtype;
	  memcpy((char *)&inaddr.sin_addr,
		 (char *)host_ptr->h_addr,
		 sizeof(inaddr.sin_addr));		 
	} 
      else 
	{
	  inaddr.sin_family = AF_INET;
	}
      addr = (struct sockaddr *) &inaddr;
      addrlen = sizeof (struct sockaddr_in);
      inaddr.sin_port = display + X_TCP_PORT;
      inaddr.sin_port = htons(inaddr.sin_port);
      /*
       * Open the network connection.
       */
      if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0){
	return(-1);	    /* errno set by system call. */}
      /* make sure to turn off TCP coalescence */
#ifdef TCP_NODELAY
      {
	int mi = 1;
	setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof (int));
      }
#endif
    }

    /*
     * Changed 9/89 to retry connection if system call was interrupted.  This
     * is necessary for multiprocessing implementations that use timers,
     * since the timer results in a SIGALRM.	-- jdi
     */
    while (connect(fd, addr, addrlen) == -1) {
	if (errno != EINTR) {
  	    (void) close (fd);
  	    return(-1); 	    /* errno set by system call. */
	}
      }
  }

  /*
   * Return the id if the connection succeeded.
   */
#endif
  return(fd);
}

/*
 *	static int waitForSocket(fd, timeout)
 *
 * Description
 *
 *	Waits for some data to be available on the given socket.
 *
 * Inputs
 *
 *	fd    : File descriptor for socket to wait on
 *	timeout: 
 *		Value in milliseconds to wait before timing out.  If zero, wait
 *		until there's input with no timeout.
 *
 * Outputs
 *
 *	True if there was input available, false if it timed out.
 */
static int waitForSocket(fd, timeout)
int	fd, timeout;
{
  struct timeval time, *timePtr;
#ifdef FD_SET
  fd_set	fds;

  FD_ZERO(&fds);
  FD_SET(fd, &fds);
#else
  int		fds;

  fds = 1 << (fd - 1);
#endif

  if (timeout) {
    time.tv_sec = timeout / 1000;
    time.tv_usec = (timeout % 1000) * 1000;
    timePtr = &time;
  } else {
    timePtr = NULL;
  }

  if (select(getdtablesize(), &fds, NULL, NULL, timePtr)) {
    return (1);
  } else {
    return (0);
  }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.