#!/usr/bin/perl
'di ';
'ds 00 \\"';
'ig 00 ';
#
#       THIS PROGRAM IS ITS OWN MANUAL PAGE.  INSTALL IN man & bin.
#

use 5.001;
use IO::Socket;

# system requirements:
# 	must have 'nslookup' and 'hostname' programs.

# $Header: /home/muir/bin/RCS/expn,v 3.11 1997/09/10 08:14:02 muir Exp muir $

# TODO:
#	less magic should apply to command-line addresses
#	less magic should apply to local addresses
#	add magic to deal with cross-domain cnames
#	disconnect & reconnect after 25 commands to the same sendmail 8.8.* host

# Checklist: (hard addresses)
#	250 Kimmo Suominen <"|/usr/local/mh/lib/slocal -user kim"@grendel.tac.nyc.ny.us>
#	harry@hofmann.cs.Berkeley.EDU -> harry@tenet (.berkeley.edu)  [dead]
#	bks@cs.berkeley.edu -> shiva.CS (.berkeley.edu)		      [dead]
#	dan@tc.cornell.edu -> brown@tiberius (.tc.cornell.edu)

#############################################################################
#
#  Copyright (c) 1993 David Muir Sharnoff
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. All advertising materials mentioning features or use of this software
#     must display the following acknowledgement:
#       This product includes software developed by the David Muir Sharnoff.
#  4. The name of David Sharnoff may not be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE DAVID MUIR SHARNOFF ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL DAVID MUIR SHARNOFF BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
#
# This copyright notice derrived from material copyrighted by the Regents
# of the University of California.
#
# Contributions accepted.
#
#############################################################################

# overall structure:
#	in an effort to not trace each address individually, but rather
#	ask each server in turn a whole bunch of questions, addresses to
#	be expanded are queued up.
#
#	This means that all accounting w.r.t. an address must be stored in
#	various arrays.  Generally these arrays are indexed by the
#	string "$addr *** $server" where $addr is the address to be
#	expanded "foo" or maybe "foo@bar" and $server is the hostname
#	of the SMTP server to contact.
#

# important global variables:
#
# @hosts : list of servers still to be contacted
# $server : name of the current we are currently looking at
# @users = $users{@hosts[0]} : addresses to expand at this server
# $u = $users[0] : the current address being expanded
# $names{"$users[0] *** $server"} : the 'name' associated with the address
# $mxbacktrace{"$users[0] *** $server"} : record of mx expansion
# $mx_secondary{$server} : other mx relays at the same priority
# $domainify_fallback{"$users[0] *** $server"} : alternative names to try 
#	instead of $server if $server doesn't work
# $temporary_redirect{"$users[0] *** $server"} : when trying alternates,
#	temporarily channel all tries along current path
# $giveup{$server} : do not bother expanding addresses at $server
# $verbose : -v
# $watch : -w
# $vw : -v or -w
# $debug : -d
# $valid : -a
# $levels : -1
# $S : the socket connection to $server

$have_nslookup = 1;	# we have the nslookup program
$port = 'smtp';
$av0 = $0;
$ENV{'PATH'} .= ":/usr/etc" unless $ENV{'PATH'} =~ m,/usr/etc,;
$ENV{'PATH'} .= ":/usr/ucb" unless $ENV{'PATH'} =~ m,/usr/ucb,;
select(STDERR);

$0 = "$av0 - running hostname";
chop($name = `hostname || uname -n`);

$0 = "$av0 - lookup host FQDN and IP addr";
($hostname,$aliases,$type,$len,$thisaddr) = gethostbyname($name);

$0 = "$av0 - parsing args";
$usage = "Usage: $av0 [-1avwd] user[\@host] [user2[host2] ...]";
for $a (@ARGV) {
	die $usage if $a eq "-";
	while ($a =~ s/^(-.*)([1avwd])/$1/) {
		eval '$'."flag_$2 += 1";
	}
	next if $a eq "-";
	die $usage if $a =~ /^-/;
	&expn(&parse($a,$hostname,undef,1));
}
$verbose = $flag_v;
$watch = $flag_w;
$vw = $flag_v + $flag_w;
$debug = $flag_d;
$valid = $flag_a;
$levels = $flag_1;

die $usage unless @hosts;
if ($valid) {
	if ($valid == 1) {
		$validRequirement = 0.8;
	} elsif ($valid == 2) {
		$validRequirement = 1.0;
	} elsif ($valid == 3) {
		$validRequirement = 0.9;
	} else {
		$validRequirement = (1 - (1/($valid-3)));
		print "validRequirement = $validRequirement\n" if $debug;
	}
}

HOST:
while (@hosts) {
	$server = shift(@hosts);
	@users = split(' ',$users{$server});
	delete $users{$server};

	# is this server already known to be bad?
	$0 = "$av0 - looking up $server";
	if ($giveup{$server}) {
		&giveup('mx domainify',$giveup{$server});
		next;
	}

	# do we already have an mx record for this host?
	next HOST if &mxredirect($server,*users);

	# look it up, or try for an mx.
	$0 = "$av0 - gethostbyname($server)";

	($name,$aliases,$type,$len,$thataddr) = gethostbyname($server);
	# if we can't get an A record, try for an MX record.
	unless($thataddr) {
		&mxlookup(1,$server,"$server: could not resolve name",*users);
		next HOST;
	}
				
	# get a connection, or look for an mx
	$0 = "$av0 - socket to $server";

	$S = new IO::Socket::INET (
		'PeerAddr' => $server,
		'PeerPort' => $port,
		'Proto' => 'tcp');

	if (! $S || ($debug == 10 && $server =~ /relay\d.UU.NET$/i)) {
		$0 = "$av0 - $server: could not connect: $!\n";
		$emsg = $!;
		unless (&mxlookup(0,$server,"$server: could not connect: $!",*users)) {
			&giveup('mx',"$server: Could not connect: $emsg");
		}
		next HOST;
	}
	$S->autoflush(1);

	# read the greeting
	$0 = "$av0 - talking to $server";
	&alarm("greeting with $server",'');
	while(<$S>) {
		alarm(0);
		print if $watch;
		if (/^(\d+)([- ])/) {
			if ($1 != 220) {
				$0 = "$av0 - bad numeric response from $server";
				&alarm("giving up after bad response from $server",'');
				&read_response($2,$watch);
				alarm(0);
				print STDERR "$server: NOT 220 greeting: $_"
					if ($debug || $vw);
				if (&mxlookup(0,$server,"$server: did not respond with a 220 greeting",*users)) {
					close($S);
					next HOST;
				}
			}
			last if ($2 eq " ");
		} else {
			$0 = "$av0 - bad response from $server";
			print STDERR "$server: NOT 220 greeting: $_"
				if ($debug || $vw);
			unless (&mxlookup(0,$server,"$server: did not respond with SMTP codes",*users)) {
				&giveup('',"$server: did not talk SMTP");
			}
			close($S);
			next HOST;
		}
		&alarm("greeting with $server",'');
	}
	alarm(0);
	
	# if this causes problems, remove it
	$0 = "$av0 - sending helo to $server";
	&alarm("sending helo to $server","");
	&ps("helo $hostname");
	while(<$S>) {
		print if $watch;
		last if /^\d+ /;
	}
	alarm(0);

	# try the users, one by one
	USER:
	while(@users) {
		$u = shift(@users);
		$0 = "$av0 - expanding $u [\@$server]";

		# do we already have a name for this user?
		$oldname = $names{"$u *** $server"};

		print &compact($u,$server)." ->\n" if ($verbose && ! $valid);
		if ($valid) {
			#
			# when running with -a, we delay taking                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  