#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

int open_clientfd(char *hostname, char *port);

#define MAXLINE 512

/* usage: ./echoclient host port */
int main(int argc, char **argv)
{
    int clientfd;
    size_t n;
    char *host, *port, buf[MAXLINE];
 
    host = argv[1];
    port = argv[2];

    clientfd = open_clientfd(host, port);
    if (clientfd < 0) {
	if (clientfd == -1)
	    fprintf (stderr, "%s:%s: %s\n", host, port, strerror(errno));
	exit(1);
    }

    while (fgets(buf, sizeof buf - 1, stdin) != NULL) {
        write(clientfd, buf, strlen(buf));
        n = read(clientfd, buf, sizeof buf - 1);
        if (n >= 0) {
	    buf[n] = '\0';
	    fputs(buf, stdout);
	}
    }
    close(clientfd);
    exit(0);
}

int open_clientfd(char *hostname, char *port)
{
  int clientfd;
  struct addrinfo hints;
  struct addrinfo *hostaddresses = NULL;
  int error;

  /* Find out the server's IP address and port */
  memset(&hints, 0, sizeof hints);
  hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
  hints.ai_family = AF_INET6;
  hints.ai_socktype = SOCK_STREAM;

  error = getaddrinfo(hostname, port, &hints, &hostaddresses);
  if (error != 0) {
    freeaddrinfo(hostaddresses);
    fprintf (stderr, "%s:%s: %s\n", hostname, port, gai_strerror(error));
    return -2;
  }

  /* We take advantage of the fact that AF_* and PF_* are identical */
  clientfd = socket(hostaddresses->ai_family,
   hostaddresses->ai_socktype, hostaddresses->ai_protocol);
  if (clientfd == -1) {
    freeaddrinfo(hostaddresses);
    return -1; /* check errno for cause of error */
  }

  /* Establish a connection with the server */
  if (connect(clientfd, hostaddresses->ai_addr, hostaddresses->ai_addrlen)
   == -1) {
    freeaddrinfo(hostaddresses);
    return -1;
  }

  freeaddrinfo(hostaddresses);
  return clientfd;
}
