/*
 * whois InterNIC name directory service
 *                as defined in RFC 954.  Sends user query
 *                to whois port, copies results to stdout.
 *
 *	Originally Written by:  DDN Network Information Center.
 *	Modified by: InterNIC Registration Services
 *	This code may be freely copied for any use.
 *
 *	Tested on Sun4s running 4.1.*
 *
 *  Revised 18 March 1992 by Peter Klosky, Network Solutions, Inc.
 *  Now runs under SunOS 4.1.1; previous version had unneeded "bind."
 *  For ATT 3B2, see below.
 *
 *  Revised 31 March 1993 by Mark Kosters, Network Solutions, Inc.
 *  Now defaults to whois.internic.net
 *
 *	To compile on BSD4.[23], SunOS4.1.*, SunOS3.x, and Ultrix:
 *
 *		cc -o whois whois.c
 *
 *	Usage: whois [ -h host ] name
 *
 *	'host' may be either by name or address.
 *
 *  You may or may not need to compile this program.  If your system
 *  came with a version of "whois" with a reference to "sri-nic.arpa"
 *  or whatever, consider the following options:
 *
 *      1. Install a shell to provide the current -h option as
 *         follows:
 *           % cd /usr/ucb
 *           % mv whois whois.real
 *           % cat >whois
 *             /usr/ucb/whois.real -h nic.ddn.mil $1
 *             <control-d>
 *           % chmod 755 whois
 *      2. Patch the existing string with a patch utility such as:
 *           A. adb
 *           B. perl
 *           C. od & unod
 *           D. od & dd
 *
 *  This program has been compiled and loaded on an ATT 3B2.
 *  In this case, include sys/in.h and sys/inet.h and do not
 *  include netinet/in.h as below.  Load with -lnet and -lnsl_s.
 *  Add whois as service 43 in /etc/services.
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#define	SERVICE		"whois"
#define	PROTOCOL	"tcp"
#define	MAXTMPLEN	128	/* max length of tmp array declared below */

/* the possible host names for the whois server */
char *whois_servers[] = { "whois.internic.net",
			  NULL	/* null pointer terminates the list */
};


main(argc, argv)
char *argv[];
{
	char			*cmdname;
	int			skt;
	register FILE		*fin, *fout;
	register int		i;
	int			c;
	char			*host;
	char			tmp[MAXTMPLEN];
	struct sockaddr_in	sin;
	struct hostent		*hp;
	struct servent		*sp;

	/* save the command name (usually called "whois") */
	cmdname = argv[0];

	argc--, argv++;

	/* test for presence of the -h flag. */
	if (argc > 2 && strcmp(*argv, "-h") == 0) {
		argv++, argc--;
		/* copy specified-host pointer to the array */
		whois_servers[0] = *argv++;
		/* make the specified-host the only entry */
		whois_servers[1] = NULL;
		argc--;
	}

	/* punt if syntax is wrong */
	if (argc != 1) {
		fprintf(stderr, "usage: %s [ -h host ] name\n", cmdname);
		exit(1);
	}

	/* run thru the list of whois servers till one is found
	 * with an IP addr. Look first by hostname, then by
	 * hostaddr that fails.
	 */
	for (i = 0; ;i++)
		if (whois_servers[i] == NULL) 
			exit(1);
		else if ((hp = gethostbyname (whois_servers[i])))
			break;
		else {
			unsigned long	hostaddr;

			hostaddr = inet_addr (whois_servers[i]);
			if ((hp = gethostbyaddr (&hostaddr, 4, AF_INET)))
				break;
			else {
				fprintf(stderr, "%s: can't find host '%s'.\n",
					cmdname, whois_servers[i]);
				continue;
			}
		}


	/* create a socket */
	host = hp->h_name;
	if ((skt = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
		sprintf (tmp, "%.*s: socket", MAXTMPLEN, cmdname);
		perror(tmp);
		exit(1);
	}

	/* Now, bind to that socket */
	sin.sin_family = hp->h_addrtype;
#if 0
	if (bind (skt, &sin, sizeof (sin), 0) < 0) {
		sprintf (tmp, "%.*s: bind", MAXTMPLEN, cmdname);
		perror(tmp);
		exit(1);
	}
#endif

	/* get the port number for the whois server */
	bcopy (hp->h_addr, &sin.sin_addr, hp->h_length);
	if ((sp = getservbyname(SERVICE, PROTOCOL)) == NULL) {
		fprintf(stderr, "%s: Don't know what service %s/%s is.\n",
			cmdname, SERVICE, PROTOCOL);
		exit(1);
	}

	/* Now, connect to that port */
	sin.sin_port = sp->s_port;
	if (connect (skt, &sin, sizeof (sin)) < 0) {
		sprintf (tmp, "%.*s: connect", MAXTMPLEN, cmdname);
		perror(tmp);
		exit(1);
	}

	/* associate a STREAM to 'fin' and 'fout' from 'skt' */
	if ((fin = fdopen(skt, "r")) == NULL || (fout = fdopen(skt, "w")) == NULL) {
		perror("fdopen");
		close(skt);
		exit(1);
	}

	/* write out the request to the server (remember to terminate 
	 * with <return><newline>).
	 */
	fprintf(fout, "%s\r\n", *argv);
	fflush(fout);

	/* read back results */
	while ((c = getc(fin)) != EOF)
		putchar(c);

	return 0;
}
