#!/usr/local/bin/perl 'di'; 'ig00'; use DB_File; dbmopen(ALIASES,'/etc/aliases.db',undef) || die "can't dbmopen aliases"; require 'getopts.pl';; (&Getopts('vVs') && $#ARGV >= 0) || die "usage: $0 [-vVs] alias ...\n"; chop($host = `hostname`); ($verbose, $showall, $short) = ($opt_v, $opt_V, $opt_s); $verbose |= $showall; while ($user = shift) { local(%seen); if ($short) { print join(' ', &resolve($user)), "\n"; } else { print "$user -> ", join(', ', sort &resolve($user)), "\n"; } } sub resolve { local($addr,$alias,@list,@ilist); while ($addr = shift) { if ($seen{$addr}++) { #push(@list, $addr); next; } $addr .= "\0"; unless (defined $ALIASES{$addr}) { push(@list, &forward($addr)); next; } $alias = $ALIASES{$addr}; $alias =~ s/^\s*(.*)\s*$/$1/; if ($alias eq $addr) { push(@list, &forward($addr)); next; } if ($alias =~ /^"/) { push(@list, $alias); next; } print "[ $addr -> $alias ]\n" if $showall || ($verbose && ($alias !~ /^$addr@\w+$/ && $alias !~ /^[^!]+![^!]+$/)); if ($alias eq "$addr@$host") { push(@list, &forward($addr)); next; } if ($alias =~ /^:include:(.*)/) { unless (open(INC, $file = $1)) { print STDERR "$0: can't open $file: $!\n"; next; } @ilist = grep(!/^#/, ); for (@ilist) { s/\s//g; } close(INC); printf "[ %s -> %s ]\n", $file, join(' ', @ilist) if $verbose; push(@list,&resolve(@ilist)); } else { push(@list,&resolve(split(/\s*,\s*/,$alias))); } } return map { /([^\0]+)/ } @list; } ############################################################## sub forward { local($user) = @_; local($forward); return $user if $user =~ /^\s*"?[|\/]/; return $user if $user =~ /^\s*.+@.+$/; return $user if $user =~ /^\s*.+\\?!.+$/; return $user if $user =~ /^\s*\\/; if (($forward = &logdir($user)) && -r ($forward .= '/.forward')) { if (!open forward) { print STDERR "$0: cannot open $forward: $!\n"; } else { print "[ $user -> $forward ]\n" if $verbose; chop($user = ); close forward; print "[ $forward -> $user ]\n" if $verbose; return &resolve(split(/\s*,\s*/,$user)); } } else { #print "no forward for $user\n"; } $user = "$user " unless $forward; return $user; } ############################################################## sub logdir { if (! $been_here_before++) { # might make it much faster setpwent unless $dbm_passwd = dbmopen(PASSWD,'/etc/passwd', undef); } if ($dbm_passwd) { return '' unless defined $PASSWD{$_[0]}; local(@a); @a = split(/[\000]+/,$PASSWD{$_[0]}); return $a[$#a-1]; } else { return (getpwnam($_[0]))[7]; } } ############################################################################## # These next few lines are legal in both Perl and nroff. .00; # finish .ig 'di \" finish diversion--previous line must be blank .nr nl 0-1 \" fake up transition to first page again .nr % 0 \" start at page 1 ';<<'.ex'; #__END__ ############# From here on it's a standard manual page ############ .TH GETALIAS 1L .de M \" man page reference \\fI\\$1\\fR\\|(\\$2\)\\$3 .. .SH NAME getalias \- recursively resolve mail aliases .SH SYNOPSIS .B getalias [ .B \-v .B \-V .B \-s ] .I alias \&... .SH DESCRIPTION The .I getalias program consults the .M dbm 3X version of the .M aliases 5 database to rescursively resolve each of its arguments, printing the alias's (alphabetically sorted) resolution to the standard output, separated by commas. Include files referenced by the \fI:include:\fP syntax will be consulted, as will local users' .I ~/.forward files. .PP Arguemnts not appearing to be deliverable addresses are resolved to the form ``\fIalias-name\fP '' to indicate that such mail will probably be delivered to the mailer daemon for subsequent complaint. .PP The .B \-v option traces intermediary passes of the alias resolution for mailing lists. Watching the recursion can occasionally be entertaining and informative. .PP The .B \-V option is like .B \-v\c , except that it also includes simple ``name -> name@host'' aliases as well. These are mailboxes that simply go to another machine, rather than mailing lists requiring recursive expansion. .PP The .B \-s option suppresses printing of the original alias before its resolution. It also makes space the separator character. .SH NOTES .I Getalias is a .I perl program, so you must have .I perl on your system to run it. Since it is not compiled, you may read the program to learn more about how it works internally. .SH "SEE ALSO" .M mail 1 , .M nfinger 1 , .M perl 1 , .M dbm 3X , .M aliases 5 , .M sendmail 8 .SH AUTHOR Tom Christiansen .I "" .ex