Alias Lister For Users

Tom Christiansen tchrist at convex.COM
Mon Nov 19 01:35:56 AEST 1990


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 at pixel ]
    [ rhall -> /mnt/rhall/.forward ]
    [ /mnt/rhall/.forward -> "| /usr/local/mh/lib/slocal -user rhall" ]
    [ rmingee -> rmingee at pixel ]
    [ tchrist -> tchrist at 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, at list, at 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*.+ at .+$/;
	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 at 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 at 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 at 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 at ofinger = @finger;
	Xfor (@finger) {
	X    s/^\\//;
	X    s/\s//g;
	X    push(@nfinger, $_) unless $seen{$_}++ || m#^\s*("\s*)?[|/]#;
	X} 
	X at 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, at 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*.+ at .+$/;
	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 archive



More information about the Alt.sources mailing list