[net.sources] whois programs

rs@mirror.UUCP (10/28/85)

This sharfile contains a client and server for "whois."
The server does little more than just pass off the request to
the "finger" program, but that's enough.
The client is a from-scratch writing of whois.  It replaced
the standard "whois" because (a) we're not on ARPA (sri-nic is
useless to us)  and (b) I wanted to be able to say "whois rs@mirror"
and have it work.

Please MAIL me any bugs or problems you find...
	/r$


# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by mirror!rs on Mon Oct 28 14:51:51 EST 1985
# Contents:  whois.c whoisd.c
 
echo x - whois.c
sed 's/^XX//' > "whois.c" <<'@//E*O*F whois.c//'

XX#include <stdio.h>
XX#include <netdb.h>
XX#include <sys/types.h>
XX#include <sys/socket.h>
XX#include <netinet/in.h>


XX/* Handy shorthands. */
XX#define SOCK(Socket)	(struct sockaddr *)&(Socket)
XX#define DIE(s)		perror(s), exit(1)

XX/* Get the default host to connect to; you may want to change this. */
XX#define DEFAULT		(gethostname(Name, sizeof Name) < 0 ? "sri-nic" : Name)


XX/* Global variables. */
XXchar			*Who = "";
XXchar			*Where;
XXchar			 Name[32];
XXstruct sockaddr_in	 Socket;
XXstruct hostent		*Host;
XXstruct servent		*Service;

XX/* Linked in later. */
XXextern char		*index();


XXmain(ac, av)
XX    int			 ac;
XX    char		*av[];
XX{
XX    register FILE	*Stream;
XX    register char	*p;
XX    register int	 c;
XX    register int	 s;

XX    /* Parse JCL. */
XX    Where = DEFAULT;
XX    switch (ac)
XX    {
XX	default:
XXBad:
XX	    fprintf(stderr, "usage:\t%s [-h host] user\nor\t%s [user][@host]\n",
XX			    av[0], av[0]);
XX	    exit(1);
XX	case 1:
XX	    /* default to "@DEFAULT-HOST" */
XX	    break;
XX	case 2:
XX	    /* "user@host" "@host" "user" */
XX	    Who = av[1];
XX	    if (p = index(av[1], '@'))
XX	    {
XX		*p++ = '\0';
XX		Where = p;
XX	    }
XX	    break;
XX	case 4:
XX	    if (strcmp(av[1], "-h"))
XX		goto Bad;
XX	    /* "-h host user" */
XX	    Where = av[2];
XX	    Who = av[3];
XX    }

XX    /* Try to get host and the service. */
XX    Host = gethostbyname(Where);
XX    if (Host == NULL)
XX    {
XX	fprintf(stderr, "whois: %s: host unknown\n", Where);
XX	exit(1);
XX    }
XX    if ((Service = getservbyname("whois", "tcp")) == NULL)
XX	DIE("whois (whois/tcp unknown service)");

XX    /* Creation and bondage (kinky sex?). */
XX    if ((s = socket(Host->h_addrtype, SOCK_STREAM, 0)) < 0)
XX	DIE("whois (socket)");
XX    Socket.sin_family = Host->h_addrtype;
XX    if (bind(s, SOCK(Socket), sizeof Socket) < 0)
XX	DIE("whois (bind)");

XX    /* Connect to the server at the right port. */
XX    bcopy(Host->h_addr, (char *)&Socket.sin_addr, Host->h_length);
XX    Socket.sin_port = Service->s_port;
XX    if (connect(s, SOCK(Socket), sizeof Socket) < 0)
XX	DIE("whois (connect)");

XX    /* Send out the request. */
XX    if ((Stream = fdopen(s, "w")) == NULL)
XX	DIE("whois (fdopen to service)");
XX    fprintf(Stream, "%s\r\n", Who);
XX    (void)fflush(Stream);

XX    /* Get the response. */
XX    if ((Stream = fdopen(s, "r")) == NULL)
XX	DIE("whois (fdopen from service)");
XX    while ((c = getc(Stream)) != EOF)
XX	(void)putchar(c);
XX    (void)fclose(Stream);

XX    exit(0);
XX}
@//E*O*F whois.c//
chmod u=rw,g=rw,o=rw whois.c
 
echo x - whoisd.c
sed 's/^XX//' > "whoisd.c" <<'@//E*O*F whoisd.c//'
XX/*
XX**  A "Whois" server, TCP Port 43 (RFC 812)
XX**
XX**  Copyright, 1985, Richard E. $alz.  Permission is granted to the public
XX**  to copy and use this software without charge, provided that this notice
XX**  and any statement of authorship are reproduced on all copies.  The author
XX**  makes no warranty expressed or implied, nor assumes any liability or
XX**  responsibility for the use of this software.
XX*/

XX#include <stdio.h>
XX#include <netdb.h>
XX#include <sys/types.h>
XX#include <sys/ioctl.h>
XX#include <sys/socket.h>
XX#include <net/if.h>
XX#include <netinet/in.h>
XX#include <signal.h>
XX#include <errno.h>
XX#include <sys/wait.h>
XX#include <sys/time.h>
XX#include <sys/resource.h>


XX/* Handy shorthands. */
XX#define SIZE		256			/* This is reasonable	*/
XX#define SOCK(Socket)	(struct sockaddr *)&(Socket)	/*  For lint	*/
XX#define DIE(s)		perror(s), exit(1);	/* Say bye-bye		*/


XX/* Global variables. */
XXstruct hostent		*Host;
XXstruct servent		*Service;
XXstruct sockaddr_in	 Socket = { AF_INET };
XXint			 Size;
XXchar			 Buff[SIZE];
XXchar			 Command[SIZE];
XXchar			 LOSE_MSG[] = "Sorry; can't\n";


XX/* Linked in later. */
XXextern int		 errno;
XXextern FILE		*popen();
XXextern char		*strcpy();
XXextern char		*strcat();


XXWait()
XX{
XX    union wait	Status;

XX    while (wait3(&Status, WNOHANG, (struct rusage *)NULL) > 0)
XX	;
XX}


XXmain()
XX{
XX    register FILE		*Stream;
XX    register int		 In;
XX    register int		 Client;
XX    register int		 i;

XX    /* Who are we? */
XX    if (getuid())
XX	DIE("whoisd (not super user)");

XX    /* Where are we? */
XX    if (gethostname(Buff, sizeof Buff) < 0)
XX	DIE("whoisd (gethostname)");
XX    if ((Host = gethostbyname(Buff)) == NULL)
XX	DIE("whoisd (gethostbyname)");

XX    /* What are we trying to do? */
XX    if ((Service = getservbyname("whois", "tcp")) == NULL)
XX	DIE("whoisd (tcp/whois unknown service)");

XX#ifndef	DEBUG
XX    if (fork())
XX	exit(0);

XX    /* Open up the console for error logging, but ignore signals
XX       that come from it. */
XX    (void)freopen("/dev/console", "w", stderr);
XX    if ((i = open("/dev/tty", 2)) >= 0)
XX    {
XX	(void)ioctl(i, TIOCNOTTY, 0);
XX	(void)close(i);
XX    }
XX    (void)close(0);
XX    (void)close(1);
XX#endif	DEBUG

XX    /* Creation and bondage (my, how kinky). */
XX    Socket.sin_family = Host->h_addrtype;
XX    Socket.sin_port = Service->s_port;
XX    bcopy(Host->h_addr, (char *)&Socket.sin_addr, Host->h_length);
XX    if ((In = socket(AF_INET, SOCK_STREAM, 0)) < 0)
XX	DIE("whoisd (socket)");
XX    if (bind(In, SOCK(Socket), sizeof Socket) < 0)
XX	DIE("whoisd (bind)");

XX    if (listen(In, 5) < 0)
XX	DIE("whoisd (listen)");
XX    (void)signal(SIGCHLD, Wait);

XX    /* Service loop. */
XX    for ( ; ; )
XX    {
XX	/* Wait for something to come in. */
XX	Size = sizeof Socket;
XX	if ((Client = accept(In, SOCK(Socket), &Size)) < 0)
XX	{
XX	    if (errno != EINTR)
XX		perror("whoisd (accept)");
XX	    (void)sleep(1);
XX	    continue;
XX	}

XX	/* Spawn off a kid to handle it.  Should check for fork failure... */
XX	if (fork())
XX	{
XX	    (void)close(Client);
XX	    continue;
XX	}

XX	/* Shut down stuff the kid doesn't need, read the request. */
XX	(void)signal(SIGCHLD, SIG_IGN);
XX	if ((i = read(Client, Buff, sizeof Buff)) < 0)
XX	    DIE("whoisd (read)");

XX	/* Cons up the command line. */
XX	(void)strcpy(Command, "/usr/ucb/finger");
XX	if (i)
XX	{
XX	    /* Strip off the \r\n, append the argument. */
XX	    Buff[i - 2] = '\0';
XX	    (void)strcat(Command, " ");
XX	    (void)strcat(Command, Buff);
XX	}

XX	if ((Stream = popen(Command, "r")) == NULL)
XX	{
XX	    perror("whoisd (popen)");
XX	    (void)write(Client, LOSE_MSG, sizeof LOSE_MSG - 1);
XX	}
XX	else
XX	{
XX	    register FILE	*Reply;

XX	    Reply = fdopen(Client, "w");
XX	    while (fgets(Buff, sizeof Buff, Stream))
XX		fprintf(Reply, "%s", Buff);
XX	    (void)fflush(Reply);
XX	    if (pclose(Stream) == EOF)
XX		perror("whoisd (fclose)");
XX	}

XX	if (close(Client) < 0)
XX	    DIE("whoisd (close)");
XX	exit(0);
XX    }
XX}
@//E*O*F whoisd.c//
chmod u=rw,g=rw,o=rw whoisd.c
 
exit 0

--
Rich $alz	{mit-eddie, ihnp4!inmet, wjh12, cca, datacube} !mirror!rs
Mirror Systems	2067 Massachusetts Ave.
617-661-0777	Cambridge, MA, 02140