#define CONVERT

#include "convert.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#ifdef DEBUG
#include <curses.h>
#endif


extern int getopt();
extern char *optarg;
extern int optint, opterr;

main (argc, argv)
int argc;
char *argv[];
{
  int i;

  if (argc == 1) {
    usage (argv[0]);
    exit (0);
  }

  while ((i = getopt(argc,argv,"hr:x:?i")) != -1) {
    switch(i) {
    case 'r':
      {
	char *s;
#ifdef USE_DNS
	s=fqdn (optarg);
#else
	s=optarg;
#endif
	printf ("%s --> %s", s,  rfc2or (s));
      }
      break;
    case 'x':
      printf ("%s --> %s", optarg, or2rfc (optarg));
      break;
    case 'i':
      interactive ();
      break;
    case '?':
    case 'h':
    default:
      help (argv[0]);
    }
  }
  exit (0);
} /* main (argc, argv) */


/*************************************************************
 *
 * int help (str)
 * char *str;
 *
 ************************************************************/

int help (str)
char *str;
{
  usage (str);
  printf ("\n");
  printf ("  rfc-addr is a normal Internet address, for example\n");
  printf ("  user@domain.fi\n");
  printf ("  x400-addr is a normal X.400 address (O/R name) given in\n");
  printf ("  \"slash notation\", for example \n");
  printf ("  /S=user/O=domain/ADMD=fumail/C=fi/\n");
  printf ("  -i stands for \"interactive\". So far it can only be used \n");
  printf ("  to convert from X.400 to Internet (RFC-822) format.\n");
  printf ("\n");
  printf ("NOTE:\n");
  printf ("  This converter defaults to %s\n\n", HOST);
#ifndef USE_DNS
  printf ("  If you don't specify an Internet domain or enough X.400\n");
  printf ("  attributes, the default will be used.\n\n");
#else
  printf ("  If you don't specify enough X.400 attributes the default will\n");
  printf ("  be used.\n\n");
#endif
  printf ("  If converting addresses local to %s some\n", HOST);
  printf ("  conversions to the local part may be made, for example\n");
  printf ("  moa@funet.fi --> /G=Marko/S=Kaittola/O=funet/ADMD=fumail/C=fi/\n");
  printf ("\n");
} /* help (str) */


/************************************************************
 *
 * int usage (str)
 * char *str;
 *
 ************************************************************/
int usage (str)
char *str;
{
  char *prog;
  prog = (char *) strrchr (str, '/');
  if (prog == NULL)
    prog = str;
  else
    prog++;
  printf ("Usage: %s [-h] [-r rfc-addr] [-x x400-addr] [-i]\n", prog);
} /* usage (str) */


/************************************************************
 *
 * char *convert (addr, port)
 * char *addr;
 * int port;
 *
 ************************************************************/
char *convert (addr, port)
char *addr;
int port;
{
  int sock,i;
  struct sockaddr_in server;
  struct hostent *hp, *gethostbyname();
  char buf[1024];
  char *addr_with_cr;

  addr_with_cr = (char *)malloc (strlen (addr) + 2);
  if (addr_with_cr == 0) {
    perror ("allocating memory");
    exit (1);
  }
  sprintf (addr_with_cr, "%s\n", addr);

  sock = socket (AF_INET, SOCK_STREAM, 0);
  if (sock < 0) {
    perror ("opening stream socket");
    exit (1);
  }

  server.sin_family = AF_INET;
  hp = gethostbyname (HOST);
  if (hp == 0) {
    fprintf (stderr, "%s: unknown host", HOST);
    exit (2);
  }

  bcopy ((char *)hp->h_addr, (char *)&server.sin_addr, hp->h_length);
  server.sin_port = port;

  if (connect (sock, (struct sockaddr *)&server, sizeof server) < 0) {
    perror ("connecting stream socket");
    exit (1);
  }

  if (write (sock, addr_with_cr, strlen (addr_with_cr)) < 0) {
    perror ("writing on stream socket");
  }

  if (!(i=read (sock, buf, 1024))) {
    perror ("reading on stream socket");
  }
  buf[i] = 0;
  close (sock);
  return (strdup (buf));
} /* convert (addr, port) */


/************************************************************
 *
 * char *rfc2or (addr)
 * char *addr;
 *
 ************************************************************/
char *rfc2or (addr)
char *addr;
{
    register struct servent	*serv;

    serv = getservbyname ("rfc2or", "tcp");

    if (! serv) {
	return (convert (addr, RFC2OR));
    }
    else {
	return (convert (addr, (unsigned int) serv->s_port));
    }
				
} /* rfc2or (addr) */


/************************************************************
 *
 * char *or2rfc (addr)
 * char *addr;
 *
 ************************************************************/
char *or2rfc (addr)
char *addr;
{
    register struct servent	*serv;

    serv = getservbyname ("or2rfc", "tcp");

    if (! serv) {
	return (convert (addr, OR2RFC));
    }
    else {
	return (convert (addr, (unsigned int) serv->s_port));
    }

} /* or2rfc (addr) */


/************************************************************
 *
 * char *fqdn (addr)
 * char *addr;
 *
 ************************************************************/
char *fqdn (addr)
char *addr;
{
  char *s;
  char hostname[256];
  struct hostent *host;

  if (! strchr (addr, '@')) {
    gethostname (hostname, 255);
    hostname[255] = 0;
    host = gethostbyname (hostname);

    if (!host) {
#if defined(__convex__) || defined(RESOLV_PLUS)
      herror (hostname);
#endif
      exit (1);
    }

    /*
     *  @\0 --> +2
     */

    s = (char *) malloc (strlen (addr)
			 + strlen (host->h_name) + 2);
    if (s == 0) {
      perror ("allocating memory");
      exit (1);
    }

    sprintf (s, "%s@%s", addr, host->h_name);
  }
  else {
    s = (char *) malloc (strlen (addr) + 1);
    if (s == 0) {
      perror ("allocating memory");
      exit (1);
    }
    sprintf (s, "%s", addr);
  }
  return (s);
} /* fqdn (addr) */
