//sockets
#include <sys/socket.h>

//structs sockaddr_in, in_addr
#include <netinet/in.h>

//inet_addr(address->ind_addr)
#include <arpa/inet.h>

//net database: getservbyport, gethostbyname
#include <netdb.h>

//standard io
#include <stdio.h>

//read, write, close, exit
#include <unistd.h>

//string operations: memcpy
#include <string.h>

#include "Client1.h"


#define DEBUG

int
finger(char *address, char *query) {
  sockaddr_in sin;

  // this is an internet connection
  sin.sin_family = AF_INET;

  // find the server port number
  int port;
  struct servent *serv;
  
  serv = getservbyname("finger", "tcp");
  if (serv != NULL) {
    port = serv->s_port;
#ifdef DEBUG
    fprintf(stderr, "D:Resolved finger service at port %d\n", port);
#endif
  }
  else {
    port = 79; // defined in rfc1288
#ifdef DEBUG
    fprintf(stderr, "D:Finger service not resolved, trying %d\n", port);
#endif
  }

  sin.sin_port = port;

  // find the internet address of server
  in_addr addr;
  addr.s_addr = inet_addr(address);

  hostent *host;
  if (addr.s_addr == -1) { 
    // not a numerical address, so lookup host
    host = gethostbyname(address);

    if (host != NULL) {
      memcpy(&addr, *host->h_addr_list, sizeof(struct in_addr));
#ifdef DEBUG
      fprintf(stderr, "D:%s resolved as hostname to %s\n", address, 
	     inet_ntoa(addr));
#endif
    }
    else { // address is not a host
      fprintf(stderr, "Host not found: %s\n", address);
      return(1);
    }
  }
#ifdef DEBUG
  else
    fprintf(stderr, "D:%s resolved as numerical address\n", address);
#endif

  sin.sin_addr = addr;

  // create socket
  int sock = socket(AF_INET, SOCK_STREAM, 0);

  if (sock < 0) { // error
    fprintf(stderr, "Unable to create socket\n");
    return(1);
  }

  // connect to server
  if (connect(sock, (sockaddr *)&sin, sizeof(sin)) < 0) { //error
    fprintf(stderr, "Unable to connect to server\n");
    return(1);
  }

  // send query
  int query_len = strlen(query);
  if (write(sock, query, query_len) < query_len
      || write(sock, "\r\n", 2) < 2) {
    fprintf(stderr, "Sending query failed\n");
    close(sock);
    return(1);
  }

  // receive answer
  char buff[1000];
  int size;
  while ((size = read(sock, buff, sizeof(buff)-1)) >0) {
    buff[size]=0; // terminate incoming string
    printf("%s", buff);
  }

  if (size <0) {
    fprintf(stderr, "Error while reading result\n");
    close(sock);
    return(1);
  }

  // close connection
  close(sock);
  return(0);
}


int 
main(int argc, char **argv)
{
  if (argc <2) {
    printf("usage: fing hostname [querystring]\n");
    printf("  querystring     normally just the username, see RFC1288\n");
    return 0;
  }

  return(finger(argv[1], argc>2 ? argv[2] : ""));
}


