[comp.lang.perl] aliases.pl: lists direct sendmail aliases for a user/aliasname

composer@bucsf.bu.edu (Jeff Kellem) (03/19/90)

Here's a little utility (in perl, of course ;-) that I whipped up the other
day.  It basically displays direct sendmail aliases for some user/aliasname.
Think of it like `groups somename', but for sendmail aliases.  For example,
if you have the following in your sendmail aliases file, either
/usr/lib/aliases or /etc/aliases, usually:

# just a made-up example, that's all..
root: composer
bugs: composer
postmaster: root

then, you did ... 

	from-some-shell$ aliases.pl composer
	composer: root bugs

would be your output.

It does not follow indirect aliases, such as not recognizing that
"postmaster", above, really points to "composer", though indirectly through
"root".

`aliases.pl -help' will give a ~24 line description.  There are also a
number of comments at the top of the code about certain assumptions, etc.

This is just something I hacked up quickly, so feel free to send me any
comments/fixes/whatever...it definitely doesn't cover all possibilities, but
it does also look though :include: files for aliases and can be useful to
see what direct aliases you (or someone else) may be included in.

Enjoy...

				-jeff

Jeff Kellem
INTERNET: composer@cs.bu.edu  (or composer@bu.edu)
UUCP: ...!harvard!bu-cs!composer

p.s. you may also want to change "#!/usr/local/bin/perl -s" to 
"#!/your/path/to/perl -s", of course.  :-)
===CUT HERE===aliases.shar===
#! /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:  aliases.pl
# Wrapped by composer@bucsf on Sun Mar 18 18:26:51 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f aliases.pl -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"aliases.pl\"
else
echo shar: Extracting \"aliases.pl\" \(4589 characters\)
sed "s/^X//" >aliases.pl <<'END_OF_aliases.pl'
X#!/usr/local/bin/perl -s
X# simple argument parsing, need to finish my getopt first.  :-)
X#
X# Please refer any modifications/fixes/comments back to me.
X#
X# Jeff Kellem
X# INTERNET: composer@cs.bu.edu
X# UUCP: ...!harvard!bu-cs!composer
X#
X# file: aliases.pl
X#   (or aliases, but tcsh 5.1x [at least] has `aliases' as a builtin, argh!
X#    and, it is the same as alias!!! (well, w/o an arg it is))
X# author: Jeff Kellem <composer@cs.bu.edu>
X# date: 17 March 1990
X# description: finds sendmail aliases that a user is in immediately.  It
X#              currently does not recurse to see if other aliases will
X#              indirectly point to the user.
X#
X# limitations: * options must come first
X#              * for :include: files, assumes comment delims match, '(' and ')'
X#              * if there are no matches for USER, it just prints "USER:\n"
X#              * does not currently deal with uucp ! syntax or % ...
X#                it's simple...  :-)
X# assumptions: * currently assumes that :include: file has one user per line
X#              * tries to skip comments, as in "(comment)" in :include: file
X#
X# possible future enhancements:
X#            * hash aliases info, to speed up searches for multiple users
X#              during one run. 
X#            * speed up match, this was just a quick hack, don't grep each time
X#            * warning of mismatched comment delims, probably for another
X#              day (or program)
X#
X# notes:     * maybe -partial should just match USERNAME as a prefix without
X#              the '@' (currently matches "USERNAME@"), so you could do
X#              `aliases.pl -partial user@host-without-domain' to match against
X#              user@host.any.domain.  Comments?
X#            * but, then, do we want `aliases.pl -partial a' to match every
X#              alias that has an entry beginning with 'a'?  Comments?
X#            * or both ways, hmm...
X#
X# usage info: aliases.pl -help
X#
X
Xexit !print <<EOU if $help;
Xusage: $0 [-help] [-debug] [-verbose] [-partial] [-sort] [username ...]
X       Displays immediate sendmail aliases for USERNAME, somewhat in the
X       same vain as `groups'.  Does NOT display indirect aliases.
X       i.e. if mail is sent to the displayed aliases, it will go to
X            USERNAME.
X       Note: this does not find every possible alias that might point to
X             USERNAME, such as alias->different->USERNAME.
X             So, if you have an aliases file such as:
X                 foo: bar
X                 bar: user
X             and you do `$0 user', it will display
X	         user: bar
X             NOT
X                 user: bar foo
X
X       Options:
X	    -help	display this message
X	    -debug	show small amount of debugging info
X	    -verbose	show error msgs on opening :include: files
X	    -partial	check for partial match, will find "user@host"
X			and "user" for `$0 -partial user'
X			will NOT find "foouserbar" or "userfoo"!
X	    -sort	sorts list of aliases before printing
XEOU
X
Xdbmopen(aliases,'/usr/lib/aliases',0444) 
X    || dbmopen(aliases,'/etc/aliases',0444) 
X    || die "$0: can't dbmopen aliases: $!\n";
X
X($ARGV[0] = getlogin) || (($ARGV[0]) = getpwuid($<)) if $#ARGV == -1;
X
Xwhile ($user = shift) {
X    @list = &list_aliases($user);
X    print "$user:";
X    &print_array(@list);
X}
X
Xsub list_aliases {
X    local($user) = @_;
X    local($key,$value,@list);
X
X    print "USER=$user.\n" if $debug;
X    while (($key,$value) = each %aliases) {
X	chop($value, $key);
X	@values = split(/[\s,]+/o, $value);
X	push(@list,$key) && next
X	    if (grep(/^$user$/, @values)
X		|| ($partial && grep(/^$user@/, @values))
X		|| (($value =~ /^\s*:include:(.*)/io) && &in_file($user,$1)));
X#	if ($value =~ /^\s*:include:(.*)/i) {
X#	    push(@list,$key) 
X#		if &in_file($user,$1);
X#	}
X    }
X    return @list;
X}
X
X# "poor man's grep" -lwall, perl man page ... ;-)
X# there are probably better ways of doing this, but it's just a quick hack
X# maybe chg to read in entire file and split/grep on it
Xsub in_file {
X    local($pat,$file) = @_;
X
X    open(file) || $verbose && print STDERR "$0: can't open $file: $!\n";
X    while (<file>) {
X	chop;
X	# remove comments stupidly, will leave mismatched parens
X	while (s/\([^()\n]*\)//go) {}
X	# return TRUE if PAT in FILE
X	return (1) if ((/^\s*$pat\s*$/)
X			|| ($partial && /^\s*$pat@/));
X    }
X    return 0;  # PAT not in file
X}
X
X# stupid sub to print array .. duh ...
X# sorts array before printing if -sort option was given
Xsub print_array {
X    local(@list) = @_;
X    local($elt);
X
X    @list = sort @list if $sort;
X    while ($elt=shift @list) {
X	print " $elt";
X    }
X    print "\n";
X}
END_OF_aliases.pl
if test 4589 -ne `wc -c <aliases.pl`; then
    echo shar: \"aliases.pl\" unpacked with wrong size!
fi
chmod +x aliases.pl
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0