⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expn.pl

📁 < linux网络编程工具>>配套源码
💻 PL
📖 第 1 页 / 共 3 页
字号:
	if ($trhost{$trhost}) {
		$host = $trhost{$trhost};
	} else {
		$trhost{$trhost} = $host;
	}
	$trhost{$trhost};
}
# re-queue users if an mx record dictates a redirect
# don't allow a user to be redirected more than once
sub mxredirect
{
	local($server,*users) = @_;
	local($u,$nserver,@still_there);

	$nserver = &mx($server);

	if (&trhost($nserver) ne &trhost($server)) {
		$0 = "$av0 - mx redirect $server -> $nserver\n";
		for $u (@users) {
			if (defined $mxbacktrace{"$u *** $nserver"}) {
				push(@still_there,$u);
			} else {
				$mxbacktrace{"$u *** $nserver"} = $server;
				print "mxbacktrace{$u *** $nserver} = $server\n"
					if ($debug > 1);
				&expn($nserver,$u,$names{"$u *** $server"});
			}
		}
		@users = @still_there;
		if (! @users) {
			return $nserver;
		} else {
			return undef;
		}
	}
	return undef;
}
# follow mx records, return a hostname
# also follow temporary redirections comming from &domainify and
# &mxlookup
sub mx
{
	local($h,$u) = @_;

	for (;;) {
		if (defined $mx{&trhost($h)} && $h ne $mx{&trhost($h)}) {
			$0 = "$av0 - mx expand $h";
			$h = $mx{&trhost($h)};
			return $h;
		}
		if ($u) {
			if (defined $temporary_redirect{"$u *** $h"}) {
				$0 = "$av0 - internal redirect $h";
				print "Temporary redirect taken $u *** $h -> " if $debug;
				$h = $temporary_redirect{"$u *** $h"};
				print "$h\n" if $debug;
				next;
			}
			$htr = &trhost($h);
			if (defined $temporary_redirect{"$u *** $htr"}) {
				$0 = "$av0 - internal redirect $h";
				print "temporary redirect taken $u *** $h -> " if $debug;
				$h = $temporary_redirect{"$u *** $htr"};
				print "$h\n" if $debug;
				next;
			}
		}
		return $h;
	}
}
# look up mx records with the name server.
# re-queue expansion requests if possible
# optionally give up on this host.
sub mxlookup 
{
	local($lastchance,$server,$giveup,*users) = @_;
	local(*T);
	local(*NSLOOKUP);
	local($nh, $pref,$cpref);
	local($o0) = $0;
	local($nserver);
	local($name,$aliases,$type,$len,$thataddr);
	local(%fallback);

	return 1 if &mxredirect($server,*users);

	if ((defined $mx{$server}) || (! $have_nslookup)) {
		return 0 unless $lastchance;
		&giveup('mx domainify',$giveup);
		return 0;
	}

	$0 = "$av0 - nslookup of $server";
	open(T,">/tmp/expn$$") || die "open > /tmp/expn$$: $!\n";
	print T "set querytype=MX\n";
	print T "$server\n";
	close(T);
	$cpref = 1.0E12;
	undef $nserver;
	open(NSLOOKUP,"nslookup < /tmp/expn$$ 2>&1 |") || die "open nslookup: $!";
	while(<NSLOOKUP>) {
		print if ($debug > 2);
		if (/mail exchanger = ([-A-Za-z_.0-9+]+)/) {
			$nh = $1;
			if (/preference = (\d+)/) {
				$pref = $1;
				if ($pref < $cpref) {
					$nserver = $nh;
					$cpref = $pref;
				} elsif ($pref) {
					$fallback{$pref} .= " $nh";
				}
			}
		}
		if (/Non-existent domain/) {
			#
			# These addresss are hosed.  Kaput!  Dead! 
			# However, if we created the address in the
			# first place then there is a chance of 
			# salvation.
			#
			1 while(<NSLOOKUP>);	
			close(NSLOOKUP);
			return 0 unless $lastchance;
			&giveup('domainify',"$server: Non-existent domain",undef,1);
			return 0;	
		}
				
	}
	close(NSLOOKUP);
	unlink("/tmp/expn$$");
	unless ($nserver) {
		$0 = "$o0 - finished mxlookup";
		return 0 unless $lastchance;
		&giveup('mx domainify',"$server: Could not resolve address");
		return 0;
	}

	# provide fallbacks in case $nserver doesn't work out
	if (defined $fallback{$cpref}) {
		$mx_secondary{$server} = $fallback{$cpref};
	}

	$0 = "$av0 - gethostbyname($nserver)";
	($name,$aliases,$type,$len,$thataddr) = gethostbyname($nserver);

	unless ($thataddr) {
		$0 = $o0;
		return 0 unless $lastchance;
		&giveup('mx domainify',"$nserver: could not resolve address");
		return 0;
	}
	print "MX($server) = $nserver\n" if $debug;
	print "$server -> $nserver\n" if $vw && !$debug;
	$mx{&trhost($server)} = $nserver;
	# redeploy the users
	unless (&mxredirect($server,*users)) {
		return 0 unless $lastchance;
		&giveup('mx domainify',"$nserver: only one level of mx redirect allowed");
		return 0;
	}
	$0 = "$o0 - finished mxlookup";
	return 1;
}
# if mx expansion did not help to resolve an address
# (ie: foo@bar became @baz:foo@bar, then undo the 
# expansion).
# this is only used by &final
sub mxunroll
{
	local(*host,*addr) = @_;
	local($r) = 0;
	print "looking for mxbacktrace{$addr *** $host}\n"
		if ($debug > 1);
	while (defined $mxbacktrace{"$addr *** $host"}) {
		print "Unrolling MX expnasion: \@$host:$addr -> " 
			if ($debug || $verbose);
		$host = $mxbacktrace{"$addr *** $host"};
		print "\@$host:$addr\n" 
			if ($debug || $verbose);
		$r = 1;
	}
	return 1 if $r;
	$addr = "\@$host:$addr"
		if ($host =~ /\./);
	return 0;
}
# register a completed expnasion.  Make the final address as 
# simple as possible.
sub final
{
	local($addr,$host,$name,$error) = @_;
	local($he);
	local($hb,$hr);
	local($au,$ah);

	if ($error =~ /Non-existent domain/) {
		# 
		# If we created the domain, then let's undo the
		# damage...
		#
		if (defined $create_host_backtrack{"$addr *** $host"}) {
			while (defined $create_host_backtrack{"$addr *** $host"}) {
				print "Un&domainifying($host) = " if $debug;
				$host = $create_host_backtrack{"$addr *** $host"};
				print "$host\n" if $debug;
			}
			$error = "$host: could not locate";
		} else {
			# 
			# If we only want valid addresses, toss out
			# bad host names.
			#
			if ($valid) {
				print STDERR "\@$host:$addr ($name) Non-existent domain\n";
				return "";
			}
		}
	}

	MXUNWIND: {
		$0 = "$av0 - final parsing of \@$host:$addr";
		($he = $host) =~ s/(\W)/\\$1/g;
		if ($addr !~ /@/) {
			# addr does not contain any host
			$addr = "$addr@$host";
		} elsif ($addr !~ /$he/i) {
			# if host part really something else, use the something
			# else.
			if ($addr =~ m/(.*)\@([^\@]+)$/) {
				($au,$ah) = ($1,$2);
				print "au = $au ah = $ah\n" if $debug;
				if (defined $temporary_redirect{"$addr *** $ah"}) {
					$addr = "$au\@".$temporary_redirect{"$addr *** $ah"};
					print "Rewrite! to $addr\n" if $debug;
					next MXUNWIND;
				}
			}
			# addr does not contain full host
			if ($valid) {
				if ($host =~ /^([^\.]+)(\..+)$/) {
					# host part has a . in it - foo.bar
					($hb, $hr) = ($1, $2);
					if ($addr =~ /\@([^\.\@]+)$/ && ($1 eq $hb)) {
						# addr part has not . 
						# and matches beginning of
						# host part -- tack on a 
						# domain name.
						$addr .= $hr;
					} else {
						&mxunroll(*host,*addr) 
							&& redo MXUNWIND;
					}
				} else {
					&mxunroll(*host,*addr) 
						&& redo MXUNWIND;
				}
			} else {
				$addr = "${addr}[\@$host]"
					if ($host =~ /\./);
			}
		}
	}
	$name = "$name " if $name;
	$error = " $error" if $error;
	if ($valid) {
		push(@final,"$name<$addr>");
	} else {
		push(@final,"$name<$addr>$error");
	}
	"\t$name<$addr>$error\n";
}

sub alarm
{
	local($alarm_action,$alarm_redirect,$alarm_user) = @_;
	alarm(3600);
	$SIG{ALRM} = 'handle_alarm';
}
# this involves one great big ugly hack.
# the "next HOST" unwinds the stack!
sub handle_alarm
{
	&giveup($alarm_redirect,"Timed out during $alarm_action",$alarm_user);
	next HOST;
}

# read the rest of the current smtp daemon's response (and toss it away)
sub read_response
{
	local($done,$watch) = @_;
	local(@resp);
	print $s if $watch;
	while(($done eq "-") && ($s = <$S>) && ($s =~ /^\d+([- ])/)) {
		print $s if $watch;
		$done = $1;
		push(@resp,$s);
	}
	return @resp;
}
# print args if verbose.  Return them in any case
sub verbose
{
	local(@tp) = @_;
	print "@tp" if $verbose;
}
# to pass perl -w:
@tp;
$flag_a;
$flag_d;
$flag_1;
%already_domainify_fellback;
%already_mx_fellback;
&handle_alarm;
################### BEGIN PERL/TROFF TRANSITION 
.00 ;	

'di
.nr nl 0-1
.nr % 0
.\\"'; __END__ 
.\" ############## END PERL/TROFF TRANSITION
.TH EXPN 1 "March 11, 1993"
.AT 3
.SH NAME
expn \- recursively expand mail aliases
.SH SYNOPSIS
.B expn
.RI [ -a ]
.RI [ -v ]
.RI [ -w ]
.RI [ -d ]
.RI [ -1 ]
.IR user [@ hostname ]
.RI [ user [@ hostname ]]...
.SH DESCRIPTION
.B expn
will use the SMTP
.B expn
and 
.B vrfy
commands to expand mail aliases.  
It will first look up the addresses you provide on the command line.
If those expand into addresses on other systems, it will 
connect to the other systems and expand again.  It will keep 
doing this until no further expansion is possible.
.SH OPTIONS
The default output of 
.B expn
can contain many lines which are not valid
email addresses.  With the 
.I -aa
flag, only expansions that result in legal addresses
are used.  Since many mailing lists have an illegal
address or two, the single
.IR -a ,
address, flag specifies that a few illegal addresses can
be mixed into the results.   More 
.I -a
flags vary the ratio.  Read the source to track down
the formula.  With the
.I -a
option, you should be able to construct a new mailing
list out of an existing one.
.LP
If you wish to limit the number of levels deep that 
.B expn
will recurse as it traces addresses, use the
.I -1
option.  For each 
.I -1
another level will be traversed.  So, 
.I -111
will traverse no more than three levels deep.
.LP
The normal mode of operation for
.B expn
is to do all of its work silently.
The following options make it more verbose.
It is not necessary to make it verbose to see what it is
doing because as it works, it changes its 
.BR argv [0]
variable to reflect its current activity.
To see how it is expanding things, the 
.IR -v ,
verbose, flag will cause 
.B expn 
to show each address before
and after translation as it works.
The 
.IR -w ,
watch, flag will cause
.B expn
to show you its conversations with the mail daemons.
Finally, the 
.IR -d ,
debug, flag will expose many of the inner workings so that
it is possible to eliminate bugs.
.SH ENVIRONMENT
No enviroment variables are used.
.SH FILES
.PD 0
.B /tmp/expn$$
.B temporary file used as input to 
.BR nslookup .
.SH SEE ALSO
.BR aliases (5), 
.BR sendmail (8),
.BR nslookup (8),
RFC 823, and RFC 1123.
.SH BUGS
Not all mail daemons will implement 
.B expn
or
.BR vrfy .
It is not possible to verify addresses that are served
by such daemons.
.LP
When attempting to connect to a system to verify an address,
.B expn
only tries one IP address.  Most mail daemons
will try harder.
.LP
It is assumed that you are running domain names and that 
the 
.BR nslookup (8) 
program is available.  If not, 
.B expn
will not be able to verify many addresses.  It will also pause
for a long time unless you change the code where it says
.I $have_nslookup = 1
to read
.I $have_nslookup = 
.IR 0 .
.LP
Lastly, 
.B expn
does not handle every valid address.  If you have an example,
please submit a bug report.
.SH CREDITS
In 1986 or so, Jon Broome wrote a program of the same name
that did about the same thing.  It has since suffered bit rot
and Jon Broome has dropped off the face of the earth!
(Jon, if you are out there, drop me a line)
.SH AVAILABILITY
The latest version of 
.B expn
is available through anonymous ftp at
.IR ftp://ftp.idiom.com/pub/muir-programs/expn .
.SH AUTHOR
.I David Muir Sharnoff\ \ \ \ <muir@idiom.com>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -