/*
 * File: tcp.c
 *
 * Copyright (C) 1995 Sun Microsystems Inc.
 * All Rights Reserved.
 */


/*
 *    Change Log
 * ============================================================================
 * Author      Date       Change 
 * sbb	     16 Sep 95	  Created.
 *
 */


#include "gstpub.h"

#if STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#endif /* STDC_HEADERS */

#include <netdb.h>

#include <stdio.h>

/* static struct hostent myHostEnt;

static char* aliases[] = { "foo.bar.com", "loonie toons", 0 }; */


/* This routine exists because of a highly questionable decision by someone to
 * make the storage returned by gethostbyname be malloc'ed and then freed
 * before returning the value.  Gee..I hope you allocated enough storage for
 * your copy BEFORE you try to copy hostEnt, because  afterwards, if you
 * malloc, you'll get back the storage that I was using.
 * 
 * What a great design.  Makes your programs buggy as hell, but *IT DOESN'T
 * LEAK STORAGE*. Grr.......
 */
static struct hostent *cloneHostEnt(hostEnt)
struct hostent *hostEnt;
{
  char nameCopy[50];
  char *aliasesVec[50], **destAliasPtr, **srcAliasPtr, *aliasData;
  char aliasesBuf[2000], *aliasBufPtr;
  char *addrVec[50], addrBuf[2000], **destAddrPtr, **srcAddrPtr, *addrBufPtr,
	*addrData;
  int addrType, addrLength;

  strcpy(nameCopy, hostEnt->h_name);
  
  for (destAliasPtr = aliasesVec, aliasBufPtr = aliasesBuf,
       srcAliasPtr = hostEnt->h_aliases; *srcAliasPtr;
       destAliasPtr++, srcAliasPtr++) {
    *destAliasPtr = aliasBufPtr;
    strcpy(aliasBufPtr, *srcAliasPtr);
    aliasBufPtr += strlen(*srcAliasPtr) + 1;
  }
  *destAliasPtr++ = NULL;

  addrType = hostEnt->h_addrtype;
  addrLength = hostEnt->h_length;
  
  for (destAddrPtr = addrVec, addrBufPtr = addrBuf,
       srcAddrPtr = hostEnt->h_addr_list; *srcAddrPtr;
       srcAddrPtr++, destAddrPtr++) {
    *destAddrPtr = addrBufPtr;
    memcpy(addrBufPtr, *srcAddrPtr, addrLength);
    addrBufPtr += addrLength;
  }

  *destAddrPtr++ = NULL;

  /* Now we can kiss the old host ent goodbye */

  hostEnt = (struct hostent *)malloc(sizeof(struct hostent));
  hostEnt->h_name = (char *)malloc(strlen(nameCopy) + 1);
  strcpy((char *)hostEnt->h_name, nameCopy);

  hostEnt->h_aliases = (char **)malloc((destAliasPtr - aliasesVec) * sizeof(char *));
  aliasData = (char *)malloc(aliasBufPtr - aliasesBuf);
  memcpy(aliasData, aliasesBuf, aliasBufPtr - aliasesBuf);
  for (destAliasPtr = hostEnt->h_aliases, aliasBufPtr = aliasData,
       srcAliasPtr = aliasesVec; *srcAliasPtr;
       destAliasPtr++, srcAliasPtr++) {
    *destAliasPtr = aliasBufPtr;
    aliasBufPtr += strlen(aliasBufPtr) + 1;
  }
  
  *destAliasPtr = NULL;

  hostEnt->h_addrtype = addrType;
  hostEnt->h_length = addrLength;

  hostEnt->h_addr_list = (char **)malloc((destAddrPtr - addrVec) * sizeof(char *));

  addrData = (char *)malloc(addrBufPtr - addrBuf);
  memcpy(addrData, addrBuf, addrBufPtr - addrBuf);

  for (destAddrPtr = hostEnt->h_addr_list, addrBufPtr = addrData,
       srcAddrPtr = addrVec;
       *srcAddrPtr;
       srcAddrPtr++, destAddrPtr++) {
    *destAddrPtr = addrBufPtr;
    addrBufPtr += addrLength;
  }
  
  *destAddrPtr = NULL;

  return (hostEnt);
}

static struct hostent *myGetHostByName(name)
char *name;
{
  struct hostent *hostEnt;

  hostEnt = gethostbyname(name);
  return (cloneHostEnt(hostEnt));
}

void initTCP()
{

  defineCFunc("gethostbyname", myGetHostByName);
  defineCFunc("gethostbyaddr", gethostbyaddr);
/*  defineCFunc("gethostent", gethostent); */
  defineCFunc("sethostent", sethostent);
  defineCFunc("endhostent", endhostent);
}
