#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <poll.h>
#include <netinet/in.h>
#include <netdb.h>

#define K	1024
#define PORT	47350

int main(int argc, char *argv[])
{
  char *username = getenv("USER");
  struct hostent *he;
  struct sockaddr_in server;
  struct pollfd fds[2];
  char cbuf[K], buf[K];
  int sock, r, n;
  
  if (argc < 2) {
    fprintf(stderr,"Usage: chat <hostname>\n");
    return 0;
  }
  
  if (username == NULL) username = "sbaker";

  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0) {
    perror("socket");
    exit(1);
  }
  
  server.sin_family = AF_INET;
  if ((he = gethostbyname(argv[1])) == NULL) {
    fprintf(stderr,"Unknown host: %s\n", argv[1]);
    exit(1);
  }
  memcpy(&server.sin_addr, he->h_addr, he->h_length);
  server.sin_port = htons(47350);
  
  if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
    perror("connect");
    exit(1);
  }
  
  fds[0].fd = 0;
  fds[0].events = POLLIN;
  fds[1].fd = sock;
  fds[1].events = POLLIN;

  while(1) {
    r = poll(fds, 2, -1);
    if (r <= 0) continue;
    
    if (fds[0].revents & (POLLERR | POLLHUP)) break;
    if (fds[0].revents & POLLIN) {
      if (fgets(cbuf, K, stdin) == NULL) break;
      snprintf(buf, K, "%s: %s", username, cbuf);
      if (write(sock, buf, strlen(buf)) < 0) break;
    }
    if (fds[1].revents & (POLLERR | POLLHUP)) break;
    if (fds[1].revents & POLLIN) {
      if ((r = read(sock, buf, K)) < 0) break;
      printf("%.*s", r, buf);
    }
  }
  return 0;
}
