/* common library of socket code */

#include "sock_lib.h"
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>

void
die(char *msg)
{
  printf("FATAL ERROR: %s\n", msg);
  exit(1);
}

void
print_sockaddr_in(addr)
     struct sockaddr_in *addr;
{
  printf("%s:%d", inet_ntoa(addr->sin_addr), (int)ntohs(addr->sin_port));
}

void
print_socket_info(s)
     int s;
{
  struct sockaddr_in addr;
  int size;

  printf("<socket %d <local ", s);
  size = sizeof(addr);
  if (getsockname(s, (struct sockaddr *)&addr, &size) < 0)
    die("getsockname");
  print_sockaddr_in(&addr);
  printf("> <peer ");
  size = sizeof(addr);
  if (getpeername(s, (struct sockaddr *)&addr, &size) < 0)
    die("getpeername");
  print_sockaddr_in(&addr);
  printf(">>");
}

int
socket_to_service(char *host_name, char *svc_name, char *svc_type)
{
  struct hostent *host;
  struct servent *service;
  struct sockaddr_in local_addr, addr;
  int sock;

  host = gethostbyname(host_name);
  if (!host)
    return -1;
  bcopy((char*)host->h_addr, &addr.sin_addr, sizeof(addr.sin_addr));
  service = getservbyname(svc_name, svc_type);
  if (!service)
    return -2;
  addr.sin_family = AF_INET;
  addr.sin_port = service->s_port;
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0) {
    perror("socket");
    return -3;
  }
  local_addr.sin_family = AF_INET;
  local_addr.sin_port = 0;
  local_addr.sin_addr.s_addr = INADDR_ANY;
  if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
    close(sock);
    perror("bind");
    printf("could not bind socket to ");
    print_sockaddr_in(&local_addr);
    printf("\n");
    return -4;
  }
  if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    close(sock);
    perror("connect");
    printf("could not connect to ");
    print_sockaddr_in(&addr);
    printf("\n");
    return -5;
  }
#if 0
  printf("opened socket: ");
  print_socket_info(sock);
  printf("\n");
#endif
  return sock;
}
