#include "ipxtund.h"

ssize_t readn(int fd, void *vptr, size_t n)
{
  size_t nleft;
  ssize_t nread;
  void *ptr;
  
  ptr = vptr;
  nleft = n;
  while (nleft > 0) {
    if ((nread=read(fd,ptr,nleft)) < 0) {
      return(nread);
    }
    else if (nread == 0) {
      break;
    }
    nleft -= (size_t)nread;
    ptr = (char *)ptr + nread*sizeof(char);
  }
  return(ssize_t)(n-nleft);
}


ssize_t writen(int fd, const void *vptr, size_t n)
{
  size_t nleft;
  ssize_t nwritten;
  const void *ptr;
  
  ptr = vptr;
  nleft = n;
  while (nleft > 0) {
    if ((nwritten=write(fd,ptr,nleft)) <= 0) {
      return(nwritten);
    }
    nleft -= (size_t)nwritten;
    ptr = (char *)ptr + nwritten*sizeof(char);
  }
  return(ssize_t)n;
}


ssize_t recvn(int s, void *buf, size_t len, int flags)
{
  size_t bytesleft;
  ssize_t n;
  void *ptr;

  ptr = buf;
  bytesleft = len;
  while (bytesleft > 0) {
    if ((n=recv(s,ptr,bytesleft,flags)) < 0) {
      return(n);
    }
    bytesleft -= (size_t)n;
    ptr = (char *)ptr + n*sizeof(char);
  }
  return(ssize_t)(len-bytesleft);
}


ssize_t sendn(int s, const void *buf, size_t len, int flags)
{
  size_t bytesleft;
  ssize_t n;
  const void *ptr;

  ptr = buf;
  bytesleft = len;
  while (bytesleft > 0) {
    if ((n=send(s,(const void *)ptr,bytesleft,flags)) < 0) {
      return(n);
    }
    if (n == 0) break;
    bytesleft -= (size_t)n;
    ptr = (char *)ptr + n*sizeof(char);
  }
  return(ssize_t)len;
}


int get_inet_addr(struct in_addr *sin_addr, const char *hostname)
{
  u_long ul;
  const char *sp;
  struct hostent *hostentp;
  
  ul = inet_addr(hostname);
  if (ul == INADDR_NONE) {
    if ((hostentp = gethostbyname(hostname)) == NULL) {
      switch (h_errno) {
      case HOST_NOT_FOUND:
	sp = "Authoritative Answer Host not found";
	break;
      case TRY_AGAIN:
	sp = "Non-Authoritive Host not found, or SERVERFAIL";
	break;
      case NO_RECOVERY:
	sp = "Non recoverable errors, FORMERR, REFUSED, NOTIMP";
	break;
      case NO_DATA:
	sp = "Valid name, no data record of requested type";
	break;
      default:
	sp = "failed";
      }
      errormsg(E_ALL,"get_inet_addr","gethostbyname(%s): %s", hostname, sp);
      return -1;
    }
    memcpy((void *) sin_addr, hostentp->h_addr_list[0], sizeof(*sin_addr));
  }
  else {
    sin_addr->s_addr = ul;
  }
  return 0;
}


u_long msec_from_start(void)
{
  struct timeval tp;
  struct timezone tzp;
  
  gettimeofday(&tp, &tzp);
  return 1000 * (tp.tv_sec + 0.000001*tp.tv_usec - start_time);
}
