ftp.nice.ch/pub/next/unix/admin/msend.1.0.N.bs.tar.gz#/msend/network.c

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

/* network.c:
 *
 * raw networking commands.  these commands are independent of the
 * application protocol; they are not tuned specifically for msend,
 * but instead make up a library that i use to work with networking.
 *
 * (c) Copyright 1988, 1989, 1990 Jim Frost.  All Rights Reserved.  Please see
 * the accompanying file "Copyright" for more information.
 */

#include "Copyright"
#include "config.h"    /* for NOHERROR */
#include "msend.h"     /* for MAXHOSTNAME */
#include <sys/errno.h>

#define MAXCONNECTS 1  /* max number of connects we need */

extern errno;
extern int h_errno;

static int  init= 1;
static int  socki[MAXCONNECTS];
static char sockh[MAXCONNECTS][MAXHOSTNAME+1];

static void hinit()
{ int a;

  for (a= 0; a < MAXCONNECTS; a++)
    socki[a]= -1;
  init= 0;
}

int hopen(hostname)
char *hostname;
{ struct sockaddr_in sa;
  struct hostent     *hp;
  unsigned long address = 0;
  unsigned long inet_addr();
  int a,i;
#ifdef SECURE_PORT
  int lport = IPPORT_RESERVED - 1;
  int uid;
#endif

  if (init)
    hinit();

  /* find host table entry
   */

  if ((address = inet_addr(hostname)) == (unsigned long) -1) {
    address = 0;
    if((hp= gethostbyname(hostname)) == NULL) {
      errno= ECONNREFUSED;
#ifdef NOHERROR
      h_errno = 1; /* Unknown Host */
#endif
      return(-1);
    }
  }

  h_errno = 0;


  /* see if we're already talking
   */

  for (a= 0; (a < MAXCONNECTS) && ((socki[a] == -1) ||
             strcmp(sockh[a], address ? hostname : hp->h_name)); a++)
    ;
  if (a < MAXCONNECTS) /* great!  don't need a connection */
    return(socki[a]);

  /* find an empty spot
   */

  for (a= 0; (a < MAXCONNECTS) && (socki[a] != -1); a++)
    ;
  if (a >= MAXCONNECTS) {
    errno= EMFILE;
    return(-1);
  }

  strcpy(sockh[a],address ? hostname : hp->h_name);
  bzero(&sa,sizeof(sa));
  if (getprotobyname("tcp") == NULL) {
    errno= ENOPROTOOPT;
    return(-1);
  }
  if (address)
    sa.sin_addr.s_addr = address;
  else
    bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length);
  sa.sin_family= address ? AF_INET : hp->h_addrtype;
  i=portnum();
  sa.sin_port= htons((u_short)i);
#ifndef SECURE_PORT
  if ((socki[a]= socket(address ? AF_INET : hp->h_addrtype,SOCK_STREAM,0)) < 0)
    return(-1);
#else
  uid= geteuid();
  seteuid(ROOTUID);
  if((socki[a] = rresvport(&lport)) < 0) {
    seteuid(uid);
    return(-1);
  }
  seteuid(uid);
#endif
#if defined(h_addr)  /* 4.3 or greater system. Has "h_addr_list". */
  while((connect(socki[a],&sa,sizeof sa) < 0)) {
    (void) close(socki[a]);
#ifdef SECURE_PORT
    if (errno == EADDRINUSE) {
      lport--;
      seteuid(ROOTUID);
      if((socki[a] = rresvport(&lport)) < 0) {
	seteuid(uid);
	return(-1);
      }
      seteuid(uid);
      continue;
    }
#endif
    if (address) 
      return(-1);
    if (!hp->h_addr_list[1])
      return(-1);
    hp->h_addr_list++;
    bcopy(hp->h_addr_list[0],&sa.sin_addr,hp->h_length);
#ifndef SECURE_PORT
    if ((socki[a]= socket( hp->h_addrtype,SOCK_STREAM,0)) < 0)
      return(-1);
#else
    seteuid(ROOTUID);
    if((socki[a] = rresvport(&lport)) < 0) {
      seteuid(uid);
      return(-1);
    }
    seteuid(uid);
#endif
  }
#else
#ifdef SECURE_PORT
for(;;) {
#endif
  if (connect(socki[a],&sa,sizeof sa) < 0) {
    (void) close(socki[a]);
#ifndef SECURE_PORT
    return(-1);
#else
    if (errno == EADDRINUSE) {
      lport--;
      seteuid(ROOTUID);
      if((socki[a] = rresvport(&lport)) < 0) {
	seteuid(uid);
	return(-1);
      }
      seteuid(uid);
      continue;
    }
    break;
#endif
  }
}

#endif
  /* at this point you should be connected to the host for commands */

  return(socki[a]);
}

/* close a single network connection
 */

void hclose(s)
int s;
{ int a;

  for (a= 0; (a < MAXCONNECTS) && (socki[a] != s); a++)
  if (a < MAXCONNECTS) {
    close(socki[a]);
    socki[a]= -1;
  }
  else        /* not one of ours, but close it anyway */
    close(s);
}

/* this closes all open network connections
 */

void hcleanup()
{ int     a;

  for (a= 0; a < MAXCONNECTS; a++)
    if (socki[a] != -1) {
      close(socki[a]);
      socki[a]= -1;
    }
}

int hread(s,buf,n)
int  s;
char *buf;
int  n;
{ int bcount,                      /* counts bytes read */
      br;                          /* bytes read this pass */

  bcount= 0;
  br= 0;
  while (bcount < n) {             /* loop until full buffer */
    if ((br= read(s,buf,n-bcount)) > 0) {
      bcount += br;                /* increment byte counter */
      buf += br;                   /* move buffer ptr for next read */
    }
    if (br == 0)                    /* EOF */
      return(0);
    if (br < 0)                    /* signal an error to the caller */
      return(-1);
  }
  return(bcount);
}

int hwrite(s,buf,n)
int  s;
char *buf;
int  n;
{ int bcount,
      bw;

  bcount=0;
  while (bcount < n) {
    if ((bw= write(s,buf,n-bcount))>0) {
      bcount += bw;
      buf += bw;
    }
    if (bw < 0)
      return(-1);
  }
  return(bcount);
}

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