#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <linux/route.h>
#include <linux/if_ether.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <getopt.h>
#include <stdio.h>

char *pszProgram;

void usage (void)
  {
    fprintf (stderr,
	     "usage: %s -t {addr|name} {IP.ADDR | name}\n",
	     pszProgram);
  }

#define BY_NAME   1
#define BY_ADDR   2

void print_addr (char *host_addr, int index_number, int last_field)
  {
    struct in_addr addr;
/*
 * Print the address
 */
    memcpy (&addr, host_addr, sizeof (addr));
    printf ("%s", inet_ntoa (addr));
/*
 * Print the seperator
 */
    if (last_field)
      {
	printf ("\n");
      }
    else
      {
	printf (" ");
      }
  }

void print_name (char *host_name, int index_number, int last_field)
  {
/*
 * Print the name
 */
    printf ("%s", host_name);
/*
 * Print the seperator
 */
    if (last_field)
      {
	printf ("\n");
      }
    else
      {
	printf (" ");
      }
  }

int print_hosts (struct in_addr *addr, int all)
  {
    struct hostent *host;

    host = gethostbyaddr ((char *) addr, sizeof (*addr), AF_INET);
    if (host == (struct hostent *) 0)
      {
	perror ("gethostbyaddr");
	return 1;
      }
/*
 * If all entries are to be processed then print them.
 */
    if (all)
      {
	char **list_ptr = host->h_aliases;
	char *item_ptr  = *list_ptr++;
	int  last       = item_ptr == (char *) 0;
	int  count      = 0;
	
	print_name ((char *) host->h_name, count++, last);
	
	while (!last)
	  {
	    last      = *list_ptr == (char *) 0;
	    print_name (item_ptr, count++, last);
	    item_ptr  = *list_ptr++;
	  }
      }
/*
 * Print the primary item only.
 */
    else
      {
	print_name ((char *) host->h_name, 0, 1);
      }
  }

int main (int argc, char **argv)
  {
    struct in_addr addr;
    struct hostent *host;
    int            nOpt;
    int            funct = 0;
    int		   all   = 0;
    int            full  = 0;
    static char    szOptions[] = "at:";
/*
 * The parameter count must be valid
 */
    pszProgram = argv[0];

    nOpt = getopt (argc, argv, szOptions);
    while (nOpt != EOF)
      {
	switch (nOpt)
	  {
	  case 'a':
	    all = 1;
	    break;

	  case 't':
	    if (strcasecmp ("full", optarg) == 0)
	      {
		funct = BY_NAME;
		full  = 1;
		break;
	      }
	    
	    if (strcasecmp ("name", optarg) == 0)
	      {
		funct = BY_NAME;
		break;
	      }

	    if (strcasecmp ("addr", optarg) == 0)
	      {
		funct = BY_ADDR;
		break;
	      }
	    usage();
	    return 1;

	  case '?':
	  default:
	    usage();
	    return 1;
	  }
	nOpt = getopt (argc, argv, szOptions);
      }
/*
 * Ignore the '-a' parameter if requested a full translation
 */
    if (all && full)
      {
	fprintf (stderr, "-a ignored with -t full\n");
	all = 0;
      }
/*
 * Branch on the requested operation
 */
    switch (funct)
      {
      case BY_NAME:
	if (argc <= optind)
	  {
	    usage();
	    return 1;
	  }

	host = gethostbyname (argv [optind++]);
	if (host == (struct hostent *) 0)
	  {
	    perror ("gethostbyname");
	    return 1;
	  }
/*
 * If all addresses are to be printed then write them to the output
 */
	if (all)
	  {
	    char *item_ptr;
	    char **list_ptr = host->h_addr_list;
	    int  count      = 0;
	    int  last       = 0;
	    while ((item_ptr = *list_ptr++) != (char *) 0)
	      {
		last = *list_ptr == (char *) 0;
		print_addr (item_ptr, count++, last);
	      }
	  }
/*
 * Print the FQDN (ala sendmail) name.
 */
	else
	  {
	    if (full != 0)
	      {
		memcpy (&addr, host->h_addr_list[0], sizeof (addr));
		host = gethostbyaddr ((char *) &addr, sizeof (addr), AF_INET);
		if (host == (struct hostent *) 0)
		  {
		    perror ("gethostbyaddr");
		    return 1;
		  }

		if (print_hosts (&addr, 0) != 0)
		  {
		    return 1;
		  }
		break;
	      }
/*
 * Print the primary item only.
 */
	    print_addr (host->h_addr_list[0], 0, 1);
	  }
	break;

      case BY_ADDR:
	if (argc <= optind)
	  {
	    usage();
	    return 1;
	  }

	addr.s_addr = inet_addr (argv [optind++]);
	if (print_hosts (&addr, all) != 0)
	  {
	    return 1;
	  }
	break;

      default:
	usage();
	return 1;
      }
/*
 * Success at this point.
 */
    return 0;
  }
