/* 
 * $Header: /afs/.athena.mit.edu/contrib/consult/src/expn/RCS/expn.c,v 1.4 94/09/28 11:17:40 othomas Exp $
 * $Source: /afs/.athena.mit.edu/contrib/consult/src/expn/RCS/expn.c,v $
 * $Author: othomas $
 *
 * Expn is a program that opens a tcp connection the a mail hub and 
 * queries it for recipients of mail to a certain address.
 * Original version: December 15, 1988
 */

#ifndef lint
static char *rcsid_expn_c = "$Header: /afs/.athena.mit.edu/contrib/consult/src/expn/RCS/expn.c,v 1.4 94/09/28 11:17:40 othomas Exp $";
#endif lint

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

extern int errno;
extern char *sys_errlist[];

/* Error codes */
#define ERR_USAGE     1
#define ERR_HOST      2
#define ERR_SERVICE   3
#define ERR_SOCKET    4
#define ERR_CONNECT   5
#define ERR_WRITE     6
#define ERR_RECV      7

#define DEFAULT_HOST "PACIFIC-CARRIER-ANNEX.MIT.EDU"

main(argc,argv)
  int argc;
  char *argv[];
{
    static struct servent *sp;	/* Service info from /etc/services */
    struct hostent *hp;		/* Host info */
    static int s;		/* Socket descriptor */
    static struct sockaddr_in sin; /* Internet style socket address */

    char request[BUFSIZ];
    char buf[BUFSIZ];
    int len;

    void usage_exit();

    char *host = NULL;		/* Mail host to query */
    char *recipient = 0;	/* Recipient to expn */

    char **args;		/* For parsing commandline arguments */
    
    char *whoami;

    if (whoami = strrchr(argv[0], '/'))
	whoami++;
    else
	whoami = argv[0];
    
    /* Parse commandline arguments. */
    args = argv;
    
    while (*++args != 0)
    {
	if (strcmp(*args, "-host") == 0)
	{
	    if (*args == 0)
		usage_exit();
	    else
		host = *++args;
	}
	else
	    recipient = *args;
    }
    if (recipient == 0)
	usage_exit();

    if (host == NULL) {
	if (host = strrchr(recipient, '@')) {
	    *host = 0;
	    host++;
	}
	else
	    host = DEFAULT_HOST;
    }

    if ((hp = gethostbyname(host)) == NULL)
    {
	fprintf(stderr, "%s: Unknown host %s\n", whoami, host);
	exit(ERR_HOST);
    }

    /* Get service information from /etc/services */
    if ((sp = getservbyname("smtp", "tcp")) == NULL) 
    {
	fprintf(stderr, "%s: getservbyname: %s\n", whoami, sys_errlist[errno]);
	exit(ERR_SERVICE);
    }

    /* Get an internet style stream socket */
    if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) 
    {
	fprintf(stderr, "%s: socket: %s\n", whoami, sys_errlist[errno]);
	exit(ERR_SOCKET);
    }
#ifndef SOLARIS
    bzero((char *)&sin,(int)sizeof(sin));
#else
    memset((char *)&sin, 0, (int)sizeof(sin));
#endif

    sin.sin_port = sp->s_port;
#ifndef SOLARIS
    bcopy(hp->h_addr, (char *)&sin.sin_addr, sizeof(struct in_addr));
#else
    memcpy((char *)&sin.sin_addr, hp->h_addr, sizeof(struct in_addr));
#endif
    sin.sin_family = AF_INET;

    if (connect(s, &sin, sizeof(sin)))
    {
	fprintf(stderr, "%s: connect: %s\n", whoami, sys_errlist[errno]);
	exit(ERR_CONNECT);
    }
    
    /* Try to make query */
    (void) sprintf(request, "expn %s\nquit\n", recipient);
    
    /* Send a request */
    if (write(s, request, strlen(request)) == -1)
    {
	fprintf(stderr, "%s: write: %s\n", whoami, sys_errlist[errno]);
	exit(ERR_WRITE);
    }

    /* Get response */
    while ((len = recv(s, buf, BUFSIZ, MSG_PEEK)) != 0)
    {
	if (len > 0)
	{
	    (void) read(s, buf, len);
	    write(1, buf, len);
	}
	else
	{
	    fprintf(stderr, "%s: recv: %s\n", whoami, sys_errlist[errno]);
	    exit(ERR_RECV);
	}
    }

    close(s);
    exit(0);
}

void usage_exit()
{
    fprintf(stderr, "\nUsage: expn [-host host] recipient\n");
    fprintf(stderr, "The recipient can be placed anywhere on the ");
    fprintf(stderr, "commandline.  If more than one\n");
    fprintf(stderr, "recipient appears, the last one found will be used.\n");
    fprintf(stderr, "If the host is not specified with -host and an @ ");
    fprintf(stderr, "in recipient, the text\n");
    fprintf(stderr, "following the last @ is the host.  If no host is ");
    fprintf(stderr, "specified, %s is used.\n\n", DEFAULT_HOST);
    exit(ERR_USAGE);
}
