ftp.nice.ch/pub/next/unix/network/news/slrn0.9.0.0.s.tar.gz#/slrn/src/sltcp.c

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

/*  Copyright (c) 1996 John E. Davis (davis@space.mit.edu)
 *  All rights reserved.
 */
#include "config.h"
#include "features.h"

#include <stdio.h>
#include <string.h>

#include <stdlib.h>
#include <unistd.h>

#include <errno.h>
#include <ctype.h>
#include <stdarg.h>

#include <sys/types.h>

#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif

#include <netdb.h>

#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif

#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif

#include "sltcp.h"

static int TCP_Verbose_Reporting = 0;

/* This function attempts to make a connection to a specified port on an
 * internet host.  It returns a socket descriptor upon success or -1
 * upon failure.
 */
static int get_tcp_socket (char *host, int port)
{
   char **h_addr_list;
   /* h_addr_list is NULL terminated if h_addr is defined.  If h_addr
    * is not defined, h_addr is the only element in the list.  When
    * h_addr is defined, its value is h_addr_list[0].
    */
   int h_length;
   int h_addr_type;
   char *fake_h_addr_list[2];
   unsigned long fake_addr;
   struct sockaddr_in s_in;
   int s;
   int	not_connected;
   
   /* If it does not look like a numerical address, use nameserver */
   if (!isdigit(*host) || (-1L == (long)(fake_addr = inet_addr (host))))
     {
	struct hostent *hp;
	
	hp = gethostbyname (host);
	if (hp == NULL) 
	  {
	     fprintf(stderr, "%s: Unknown host.\n", host);
	     return -1;
	  }
	
#ifdef h_addr
	h_addr_list = hp->h_addr_list;
#else
	h_addr_list = fake_h_addr_list;
	h_addr_list [0] = hp->h_addr;
	h_addr_list [1] = NULL;
#endif
	h_length = hp->h_length;
	h_addr_type = hp->h_addrtype;
     }
   else 
     {
	h_addr_list = fake_h_addr_list;
	h_addr_list [0] = (char *) &fake_addr;
	h_addr_list [1] = NULL;
	
	h_length = sizeof(struct in_addr);
	h_addr_type = AF_INET;
     }

   memset ((char *) &s_in, 0, sizeof(s_in));
   s_in.sin_family = h_addr_type;
   s_in.sin_port = htons((unsigned short) port);

   if (-1 == (s = socket (h_addr_type, SOCK_STREAM, 0)))
     {
	perror("socket");
	return -1;
     }
	
   not_connected = -1;
   
   while (not_connected 
	  && (h_addr_list != NULL) 
	  && (*h_addr_list != NULL))
     {
	char *this_host;
	
	memcpy ((char *) &s_in.sin_addr, *h_addr_list, h_length);

	this_host = (char *) inet_ntoa (s_in.sin_addr);
	
	if (TCP_Verbose_Reporting) fprintf (stderr, "trying %s\n", this_host);
	
	not_connected = connect (s, (struct sockaddr *)&s_in, sizeof (s_in));
	
	if (not_connected == -1)
	  {
#ifdef EINTR
	     if (errno == EINTR) /* If interrupted, try again. */
	       continue;
#endif
	     fprintf (stderr, "connection to %s: ", (char *) this_host);
	     perror ("");
	  }
	h_addr_list++;
     }
   
   if (not_connected) 
     {
	fprintf(stderr, "Unable to make connection. Giving up.\n");
	close (s);
	return -1;
     }
   return s;
}

   
int sltcp_open_connection (SLTCP_Type *tcp, char *host, int port)
{
   int rd, wd;
   FILE *r, *w;
   
   if (tcp == NULL) return -1;
   
   tcp->fp_read = tcp->fp_write = NULL;
   
   rd = get_tcp_socket (host, port);
   if (rd == -1) return -1;
   
   /* Now setup for buffered i/o */
   
   if (NULL == (r = fdopen (rd, "r")))
     {
	fprintf (stderr, "fdopen for read failed.");
	close (rd);
	return (-1);
     }
   
   if (-1 == (wd = dup (rd)))
     {
	fprintf (stderr, "dup failed.");
	fclose (r);
	return -1;
     }
   
   if (NULL == (w = fdopen (wd, "w")))
     {
	fprintf (stderr, "fdopen for write failed.");
	fclose (r);
	close (wd);
	return (-1);
     }
   
   tcp->fp_read = r;
   tcp->fp_write = w;
   
   return 0;
}


void sltcp_close (SLTCP_Type *tcp)
{
   if (tcp == NULL) return;
   
   if (tcp->fp_read != NULL) fclose (tcp->fp_read);
   if (tcp->fp_write != NULL) fclose (tcp->fp_write);
   
   tcp->fp_read = tcp->fp_write = NULL;
}

unsigned sltcp_fread (SLTCP_Type *tcp, char *s, unsigned int len)
{
   if ((tcp == NULL) || (tcp->fp_read == NULL))
     return 0;
   
   return fread (s, 1, len, tcp->fp_read);
}

unsigned sltcp_fwrite (SLTCP_Type *tcp, char *s, unsigned int len)
{
   if ((tcp == NULL) || (tcp->fp_write == NULL))
     return 0;
   
   return fwrite (s, 1, len, tcp->fp_write);
}

int sltcp_fputs (SLTCP_Type *tcp, char *s)
{   
   if ((tcp == NULL) || (tcp->fp_write == NULL))
     return EOF;
   
   return fputs (s, tcp->fp_write);
}

char *sltcp_fgets (SLTCP_Type *tcp, char *s, int size)
{   
   if ((tcp == NULL) || (tcp->fp_read == NULL))
     return NULL;
   
   return fgets (s, size, tcp->fp_read);
}

int sltcp_fflush (SLTCP_Type *tcp)
{
   if ((tcp == NULL) || (tcp->fp_write == NULL))
     return EOF;
   
   return fflush (tcp->fp_write);
}

int sltcp_vfprintf (SLTCP_Type *tcp, char *fmt, va_list ap)
{
   if ((tcp == NULL) || (tcp->fp_write == NULL))
     return -1;
   
   if (vfprintf (tcp->fp_write, fmt, ap) < 0)
     return -1;
   
   return 0;
}

   
int sltcp_map_service_to_port (char *service)
{
   struct servent *sv;
   
   sv = getservbyname (service, "tcp");
   if (sv == NULL) return -1;
   
   return (int) ntohs (sv->s_port);
}

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