scs@lokkur.dexter.mi.us (Steve Simmons) (11/17/90)
At work we live and die by email, and we've got mail aliases coming
out our ears. I get regular requests to know who's on a given alias.
Our user community is pretty computer-naive, so telling them to grep
the alias file isn't real useful. In a flash of inspiration, I threw
together the following shell script. Install it as 'printalias' (or
the name of your choice) on a sendmail-based system, and it'll give
you nice listings of who is in any given alias. It's slow, but what
the hell. Check the values of ALIASES and SENDMAIL to be sure they're
right for your installation. Enjoy.
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: printalias
# Wrapped by scs@lokkur.dexter.mi.us on Fri Nov 16 21:29:22 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'printalias' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'printalias'\"
else
echo shar: Extracting \"'printalias'\" \(1117 characters\)
sed "s/^X//" >'printalias' <<'END_OF_FILE'
X:
X# Script to tear apart a sendmail alias and list the recipients.
X# Written by Steve Simmons at home. Public domain.
X#
X# $RCSfile: printalias,v $ $Revision: 1.1 $
X#
X# $Author: scs $ $Date: 90/11/16 17:03:06 $
X#
X# $State: Exp $ $Locker: $
X#
X# $Log: printalias,v $
X# Revision 1.1 90/11/16 17:03:06 scs
X# Initial revision
X#
X#
XSCRIPT=`basename $0`
XTEMP=/tmp/$$.${SCRIPT}
XALIASES=/usr/lib/aliases
XSENDMAIL=/usr/lib/sendmail
Xif [ ! -r $ALIASES ] ; then
X echo "${SCRIPT}: Sorry, I cannot find the aliases list ($ALIASES)."
X exit 1
Xfi
Xif [ ! -r $SENDMAIL ] ; then
X echo "${SCRIPT}: Sorry, I cannot find the alias processor ($SENDMAIL)."
X exit 1
Xfi
Xtrap "rm -f $TEMP ; exit" 0 1 2
Xfor ALIAS in $*
Xdo
X if grep "^$ALIAS:" $ALIASES 1>/dev/null 2>&1 ; then
X $SENDMAIL -bv $ALIAS > $TEMP
X echo "The \`$ALIAS' alias will send to:"
X exec < $TEMP
X while read NAME1 TRASH
X do
X read NAME2 TRASH
X read NAME3 TRASH
X read NAME4 TRASH
X read NAME5 TRASH
X read NAME6 TRASH
X echo " " $NAME1 $NAME2 $NAME3 $NAME4 $NAME5 $NAME6
X done | sed -e 's/\.\.\.//g'
X else
X echo "There is no such alias as \`$ALIAS'."
X fi
Xdone
END_OF_FILE
if test 1117 -ne `wc -c <'printalias'`; then
echo shar: \"'printalias'\" unpacked with wrong size!
fi
chmod +x 'printalias'
# end of 'printalias'
fi
echo shar: End of shell archive.
exit 0
--
"When your neighbour loses his job, it's a slowdown; when you lose your own
job, it's a recession; when an economist loses his job it's a depression."
-- "Six Ways To Define A Recession", The Economist, Nov. 3 1990.rickert@mp.cs.niu.edu (Neil Rickert) (11/18/90)
In article <1990Nov17.023351.16824@lokkur.dexter.mi.us> scs@lokkur.dexter.mi.us (Steve Simmons) writes: > >At work we live and die by email, and we've got mail aliases coming >out our ears. I get regular requests to know who's on a given alias. >Our user community is pretty computer-naive, so telling them to grep >the alias file isn't real useful. In a flash of inspiration, I threw >together the following shell script. Install it as 'printalias' (or >the name of your choice) on a sendmail-based system, and it'll give >you nice listings of who is in any given alias. It's slow, but what >the hell. Check the values of ALIASES and SENDMAIL to be sure they're >right for your installation. Enjoy. > You might want to check out the IDA sendmail kit, available at several ftp sites (uxc.cso.uiuc.edu for example). It includes a neat little command 'dbm' which can be used for the same purpose. You would just say: dbm fetch aliasname alias-file-name and get your listing. It's fast, but what the hell. -- =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= Neil W. Rickert, Computer Science <rickert@cs.niu.edu> Northern Illinois Univ. DeKalb, IL 60115. +1-815-753-6940
scs@lokkur.dexter.mi.us (Steve Simmons) (11/18/90)
In article <1990Nov17.023351.16824@lokkur.dexter.mi.us> I wrote: >Install it as 'printalias' (or the name of your choice) on a >sendmail-based system, and it'll give you nice listings of who is in >any given alias. It's slow, but what the hell. rickert@mp.cs.niu.edu (Neil Rickert) writes: > You might want to check out the IDA sendmail kit, available at several >ftp sites (uxc.cso.uiuc.edu for example). It includes a neat little >command 'dbm' which can be used for the same purpose. You would >just say: dbm fetch aliasname alias-file-name >and get your listing. It's fast, but what the hell. I live and die by IDA, and strongly recommend it to anyone dealing with sendmail on a regular basis. But its dbm utility doesn't do the job. We (and many other sites) often have heirarchical aliases -- mail to `all' is aliased to departments, departmental mail is aliased to groups, group mail is aliased to people, some of whom have their secretaries copied on everything. Doing 'dbm fetch all /usr/lib/aliases' would only list the first level. Even doing multiple probes would not get a full answer, as it would not interpret aliases of the form "include filename". Using the printalias scripot script to drive sendmail and get the complete interpretation is the only full correct answer I know of without requiring a suid program. Plus the slow correct answer is better that fast wrong one. :-) -- "When your neighbour loses his job, it's a slowdown; when you lose your own job, it's a recession; when an economist loses his job it's a depression." -- "Six Ways To Define A Recession", The Economist, Nov. 3 1990.
tchrist@convex.COM (Tom Christiansen) (11/18/90)
I haven't posted these in a while, and they've grown a bit since last
time. It does recursively resolve aliases, including following include
files and .forward files, and is pretty faster.
pixel% getalias -V postmaster
[ postmaster -> root ]
[ root -> //.forward ]
[ //.forward -> rhall, rmingee, tchrist ]
[ rhall -> rhall@pixel ]
[ rhall -> /mnt/rhall/.forward ]
[ /mnt/rhall/.forward -> "| /usr/local/mh/lib/slocal -user rhall" ]
[ rmingee -> rmingee@pixel ]
[ tchrist -> tchrist@pixel ]
postmaster -> "| /usr/local/mh/lib/slocal -user rhall", rmingee, tchrist
(stripped of @pixel at the end because that's where I ran the query.)
Also included is nfinger, which uses the same algorithm and fingers the
results of the alias expansion. It passes finger switches on to finger.
I often due this to find out who's logged in from a particular project
group:
% alias fu 'nfinger -sm'
% fu mailing-list
Getalias has an embedded man page, so install /usr/local/bin/getalias
as a link to /usr/local/man/man1/getalias, or whatever your local
paths are. Nfinger doesn't -- Use the Source.
ps: I admit to no longer recalling why nfinger didn't just call getalias.
--tom
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# getalias
# nfinger
# This archive created: Sun Nov 18 08:32:39 1990
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'getalias'" '(4807 characters)'
if test -f 'getalias'
then
echo shar: "will not over-write existing file 'getalias'"
else
sed 's/^ X//' << \SHAR_EOF > 'getalias'
X#!/usr/local/bin/perl
X'di';
X'ig00';
X
Xdbmopen(ALIASES,'/usr/lib/aliases',undef) || die "can't dbmopen aliases";
X
Xrequire 'getopts.pl';;
X
X(&Getopts('vVs') && $#ARGV >= 0) || die "usage: $0 [-vVs] alias ...\n";
X
Xchop($host = `hostname`);
X
X($verbose, $showall, $short) = ($opt_v, $opt_V, $opt_s);
X$verbose |= $showall;
X
Xwhile ($user = shift) {
X local(%seen);
X if ($short) {
X print join(' ', &resolve($user)), "\n";
X } else {
X print "$user -> ", join(', ', sort &resolve($user)), "\n";
X }
X}
X
Xsub resolve {
X local($addr,$alias,@list,@ilist);
X
X while ($addr = shift) {
X if ($seen{$addr}++) {
X #push(@list, $addr);
X next;
X }
X unless (defined $ALIASES{"$addr\0"}) {
X push(@list, &forward($addr));
X next;
X }
X chop($alias = $ALIASES{"$addr\0"});
X $alias =~ s/^\s*(.*)\s*$/$1/;
X if ($alias eq $addr) {
X push(@list, &forward($addr));
X next;
X }
X if ($alias =~ /^"/) {
X push(@list, $alias);
X next;
X }
X print "[ $addr -> $alias ]\n"
X if $showall || ($verbose
X && ($alias !~ /^$addr@\w+$/ &&
X $alias !~ /^[^!]+![^!]+$/));
X if ($alias eq "$addr@$host") {
X push(@list, &forward($addr));
X next;
X }
X if ($alias =~ /^:include:(.*)/) {
X unless (open(INC, $file = $1)) {
X print STDERR "$0: can't open $file: $!\n";
X next;
X }
X @ilist = grep(!/^#/, <INC>);
X for (@ilist) { s/\s//g; }
X close(INC);
X printf "[ %s -> %s ]\n", $file, join(' ', @ilist) if $verbose;
X push(@list,&resolve(@ilist));
X } else {
X push(@list,&resolve(split(/\s*,\s*/,$alias)));
X }
X }
X return @list;
X}
X
X
X##############################################################
X
Xsub forward {
X local($user) = @_;
X local($forward);
X
X return $user if $user =~ /^\s*"?[|\/]/;
X return $user if $user =~ /^\s*.+@.+$/;
X return $user if $user =~ /^\s*.+\\?!.+$/;
X return $user if $user =~ /^\s*\\/;
X
X if (($forward = &logdir($user)) && -r $forward .= '/.forward') {
X if (!open forward) {
X print STDERR "$0: cannot open $forward: $!\n";
X } else {
X print "[ $user -> $forward ]\n" if $verbose;
X chop($user = <forward>);
X close forward;
X print "[ $forward -> $user ]\n" if $verbose;
X return &resolve(split(/\s*,\s*/,$user));
X }
X } else {
X #print "no forward for $user\n";
X }
X $user = "$user <MAILER-DAEMON>" unless $forward;
X return $user;
X
X}
X
X##############################################################
X
Xsub logdir {
X if (! $been_here_before++) { # might make it much faster
X setpwent unless $dbm_passwd = dbmopen(PASSWD,'/etc/passwd', undef);
X }
X
X if ($dbm_passwd) {
X return '' unless defined $PASSWD{$_[0]};
X local(@a);
X @a = split(/[\000]+/,$PASSWD{$_[0]});
X return $a[$#a-1];
X } else {
X return (getpwnam($_[0]))[7];
X }
X}
X##############################################################################
X
X # These next few lines are legal in both Perl and nroff.
X
X.00; # finish .ig
X
X'di \" finish diversion--previous line must be blank
X.nr nl 0-1 \" fake up transition to first page again
X.nr % 0 \" start at page 1
X';<<'.ex'; #__END__ ############# From here on it's a standard manual page ############
X.TH GETALIAS 1L
X.de M \" man page reference
X\\fI\\$1\\fR\\|(\\$2\)\\$3
X..
X.SH NAME
Xgetalias \- recursively resolve mail aliases
X.SH SYNOPSIS
X.B getalias
X[
X.B \-v
X.B \-V
X.B \-s
X]
X.I alias
X\&...
X.SH DESCRIPTION
XThe
X.I getalias
Xprogram consults the
X.M dbm 3X
Xversion of the
X.M aliases 5
Xdatabase to rescursively resolve each of its arguments, printing
Xthe alias's (alphabetically sorted) resolution to the standard output,
Xseparated by commas.
XInclude
Xfiles referenced by the \fI:include:\fP syntax will be consulted,
Xas will local users'
X.I ~/.forward
Xfiles.
X.PP
XArguemnts not appearing to be deliverable addresses
Xare resolved to
Xthe form ``\fIalias-name\fP <MAILER-DAEMON>'' to indicate
Xthat such mail will probably be delivered to the mailer daemon
Xfor subsequent complaint.
X.PP
XThe
X.B \-v
Xoption traces intermediary passes of the alias resolution for
Xmailing lists.
XWatching the recursion can occasionally be entertaining and informative.
X.PP
XThe
X.B \-V
Xoption is like
X.B \-v\c
X, except that it also includes simple ``name -> name@host'' aliases as well.
XThese are mailboxes that simply go to another machine, rather than
Xmailing lists requiring recursive expansion.
X.PP
XThe
X.B \-s
Xoption suppresses printing of the original alias before its resolution.
XIt also makes space the separator character.
X.SH NOTES
X.I Getalias
Xis a
X.I perl
Xprogram, so you must have
X.I perl
Xon your system to run it. Since it
Xis not compiled, you may read the program to learn more about
Xhow it works internally.
X.SH "SEE ALSO"
X.M mail 1 ,
X.M nfinger 1 ,
X.M perl 1 ,
X.M dbm 3X ,
X.M aliases 5 ,
X.M sendmail 8
X.SH AUTHOR
XTom Christiansen
X.I "<tchrist@convex.com>"
X.ex
SHAR_EOF
if test 4807 -ne "`wc -c < 'getalias'`"
then
echo shar: "error transmitting 'getalias'" '(should have been 4807 characters)'
fi
chmod 775 'getalias'
fi
echo shar: "extracting 'nfinger'" '(3329 characters)'
if test -f 'nfinger'
then
echo shar: "will not over-write existing file 'nfinger'"
else
sed 's/^ X//' << \SHAR_EOF > 'nfinger'
X#!/usr/local/bin/perl
X#
X# nfinger -- finger people at their home machines
X# as defined in the /usr/lib/aliases
X# dbm file. recursively resolve all
X# aliases first, so works on lists
X
Xdbmopen(ALIAS,'/usr/lib/aliases',undef) || die "can't dbmopen aliases: $!";
X
Xchop($localhost = `hostname`);
X
X@finger_opts = ();
Xwhile ($ARGV[0] =~ /^-/) {
X if ($ARGV[0] eq '-v') {
X $verbose++;
X shift;
X } else {
X push(@finger_opts, shift);
X }
X}
X
Xwhile ($user = shift) {
X undef %seen;
X $seeking++;
X push(@finger, &resolve($user));
X}
X
Xundef %seen;
X@ofinger = @finger;
Xfor (@finger) {
X s/^\\//;
X s/\s//g;
X push(@nfinger, $_) unless $seen{$_}++ || m#^\s*("\s*)?[|/]#;
X}
X@finger = sort @nfinger;
X
Xif ($seeking && !@finger) {
X printf STDERR "$0: can't finger only pipes and files! (@ofinger)\n";
X exit 1;
X}
X
X$exec = "/usr/ucb/finger @finger_opts @finger\n";
X
Xprint $exec if $verbose;
X
X
Xexec $exec unless grep(/-.*s/, @finger_opts);
X
X
Xopen (FINGER, "$exec 2>&1 |") || die "Can't open finger pipe\n";
X
X$mask = "%-8s%s";
X$\ = "\n";
X$| = 1;
X$localhost = sprintf("%-8s", $localhost);
X
Xwhile (<FINGER>) {
X s/\s*$//;
X next if /^$/;
X if (/^\[([^\]]*)\]$/) {
X $host = sprintf("%-8s", $1);
X $sawhost = 1;
X } elsif (/^Login/) {
X if (!$printed++) {
X substr($_, 9, 0) = 'Home ';
X s/ Name/Name /;
X print;
X }
X $host = $localhost unless $sawhost;
X $sawhost = 0;
X } elsif (/^\S+:/) {
X $sawhost = /^finger:/;
X print STDERR "$host <$_>";
X } else {
X substr($_, 9, 0) = $host;
X print;
X }
X}
Xclose FINGER || die "$0: error running finger, status was $?\n";
X
X##############################################################
X
Xsub resolve {
X local($addr,$alias,@list);
X local(@addrs) = @_;
X
X for $addr (@addrs) {
X unless (defined $ALIAS{"$addr\0"}) {
X push(@list, &forward($addr));
X next;
X }
X chop($alias = $ALIAS{"$addr\0"});
X
X $alias =~ s/^\s*(.*)\s*$/$1/;
X $alias =~ s/^([^!]*)!([^!]+)$/$2@$1/;
X
X if ($alias eq "$addr@$localhost" || $alias eq $addr) {
X push(@list, &forward($addr));
X } else {
X print "[ $addr -> $alias ]\n" if $verbose;
X push(@list,&resolve(split(/\s*,\s*/,$alias)));
X }
X }
X return @list;
X}
X
X
X##############################################################
X
Xsub forward {
X local($user) = @_;
X local($forward);
X
X $seen{$addr}++ && return $addr;
X
X return $user if $user =~ /^\s*"?[|\/]/;
X return $user if $user =~ /^\s*.+@.+$/;
X return $user if $user =~ /^\s*.+\\?!.+$/;
X return $user if $user =~ /^\s*\\/;
X
X if (($forward = &logdir($user)) && -r $forward .= '/.forward') {
X if (!open forward) {
X print STDERR "$0: cannot open $forward: $!\n";
X } else {
X print "[ $user -> $forward ]\n" if $verbose;
X chop($user = <forward>);
X close forward;
X print "[ $forward -> $user ]\n" if $verbose;
X return &resolve(split(/,/,$user));
X }
X }
X return $user;
X
X}
X
X##############################################################
X
Xsub logdir {
X if (! $been_here_before++) { # might make it much faster
X setpwent unless $dbm_passwd = dbmopen(PASSWD,'/etc/passwd', undef);
X }
X
X if ($dbm_passwd) {
X return '' unless defined $PASSWD{$_[0]};
X local(@a);
X @a = split(/[\000]+/,$PASSWD{$_[0]});
X return $a[$#a-1];
X } else {
X return (getpwnam($_[0]))[7];
X }
X}
SHAR_EOF
if test 3329 -ne "`wc -c < 'nfinger'`"
then
echo shar: "error transmitting 'nfinger'" '(should have been 3329 characters)'
fi
chmod 775 'nfinger'
fi
exit 0
# End of shell archivemic@ut-emx.uucp (Mic Kaczmarczik) (11/19/90)
In article <1990Nov17.023351.16824@lokkur.dexter.mi.us>
scs@lokkur.dexter.mi.us (Steve Simmons) posted a sendmail alias
expander that used sendmail -bv to verify the alias. One advantage of
using sendmail instead of parsing the alias database directly is that
it works on systems where the alias file is distributed using Sun's
NIS (nee Yellow Pages) network database, instead of being a file on
disk.
The script below uses the same idea as Steve's script (make *sendmail*
figure things out), but instead uses the SMTP EXPN command and parses
the server's response. Since I haven't seen too much use of the
SMTP-through-a-pipe technique elsewhere (maybe for good reasons :-),
here 'tis.
--mic--
------------------------------------CUT HERE-----------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: expn
# Wrapped by mic@emx.utexas.edu on Sun Nov 18 22:02:23 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'expn' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'expn'\"
else
echo shar: Extracting \"'expn'\" \(634 characters\)
sed "s/^X//" >'expn' <<'END_OF_FILE'
X#!/bin/sh
X#
X# This hack runs sendmail in SMTP mode and uses the EXPN command to
X# expand an address into the real address(es) that the mail will be
X# delivered to. It takes advantage of sendmail's ability to read
X# SMTP commands from standard input when you use the -bs flag.
X#
X# Usage:
X# expn alias
X#
X# Output:
X# the address(es) mail sent to ``alias'' will really go to
X
Xif [ -z "$1" ]; then
X echo usage: `basename $0` sendmail-alias
X exit 1
Xfi
Xecho "expn $1
Xquit" | /usr/lib/sendmail -bs | tr -d '\015' | \
X sed -e 's/^250.*<\([^>]*\)>.*/\1/' \
X -e 's/^5[0-9][0-9].\(.*\)/\1/' \
X -e '/^[0-9][0-9][0-9] /d' | sort
Xexit 0
X
END_OF_FILE
if test 634 -ne `wc -c <'expn'`; then
echo shar: \"'expn'\" unpacked with wrong size!
fi
chmod +x 'expn'
# end of 'expn'
fi
echo shar: End of shell archive.
exit 0
------------------------------------CUT HERE-----------------------------------