/**************************************************
 *  PJ Waskiewicz                                 *
 *  3/27/2000                                     *
 *  finger.c                                      *
 *                                                *
 *  Simple finger client for communication        *
 *  with the UNIX finger socket.                  *
 *                                                *
 **************************************************
 */

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

/* Finger port */
#define SERV_SOCKET 79
#define MY_MAX 65535

void usage();

main(int argc, char *argv[]) {
  int sock_fd;
  int opt;
  int size;
  struct sockaddr_in f_sock;
  struct hostent *f_host;
  char *host = NULL;
  char *user = NULL;
  char *message;
  char answer[MY_MAX];
  opterr = 0;
  while(1) {
    opt = getopt(argc, argv, "h:u:");
    if(opt == EOF) {
      /* Check to see if we got any opts */
      if(optind == 1) {
        /* We had no opts, use localhost */
        host = malloc(strlen("localhost") + 1);
        memcpy(host, "localhost", strlen("localhost"));
        break;
      }
      else break;
    }
    else if(opt == 0x68) {
      /* A host was specified */
      host = malloc(strlen(optarg));
      memcpy(host, optarg, strlen(optarg));
    }
    else if(opt == 0x75) {
      /* A user was specified */
      user = malloc(strlen(optarg));
      memcpy(user, optarg, strlen(optarg));
    }
    else usage();
  }
  if(host == NULL) {
    host = malloc(strlen("localhost") + 1);
    memcpy(host, "localhost", strlen("localhost"));
  }
  if((f_host = gethostbyname(host)) == NULL) {
    fprintf(stderr, "%s: %s\n", host, hstrerror(h_errno));
    exit(1);
  }
  f_sock.sin_family = AF_INET;
  f_sock.sin_port = htons((u_short)SERV_SOCKET);
  f_sock.sin_addr = *(struct in_addr *)f_host->h_addr;

  if(user != NULL) {
    message = malloc(strlen(user) + 1);
    memcpy(message, user, strlen(user));
    message[strlen(user)] = '\0';
    strcat(message, "\n");
  }
  else {
    message = malloc(2);
    memcpy(message, "\n", strlen("\n"));
  }
  printf("[%s]\n", f_host->h_name);
  /* Time to set up the socket */
  if((sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
    perror("socket()");
    exit(1);
  }
  /* Now connect to it */
  if(connect(sock_fd, &f_sock, sizeof(struct sockaddr_in)) < 0) {
    perror("connect()");
    exit(1);
  }

  /* Send my message to the finger port */
  if(send(sock_fd, message, strlen(message), MSG_NOSIGNAL) < 0) {
    perror("send()");
    exit(1);
  }

  /* Get my message back */
  if((size = recv(sock_fd, answer, MY_MAX, MSG_NOSIGNAL)) < 0) {
    perror("recv()");
    exit(1);
  }
  answer[size] = '\0';
  printf("%s", answer);
  /* We're done, so let's clean up */
  if(host != NULL)
    free(host);
  if(user != NULL)
    free(user);
  free(message);
  close(sock_fd);
  exit(0);
}

void usage() {
  printf("usage: finger [ -h hostname [ -u username ] ]\n");
  exit(1);
}