#!/usr/bin/perl

use strict;
use Socket;
use vars qw($MAC_PROCESS $PS_STR $MATCH_STR $ASIP_PORT_NO $ASIP_PORT $LSOF);

# Written for linux; may have to be modified for your brand of Unix.

# Support for FreeBSD added by Joe Clarke <marcus@marcuscom.com>.
# Support could probably be extended for *BSD, but I do not have Net or
# OpenBSD machines to test with.  Code has also been cleaned up and made
# to compile under strict.
#
# The new lsof call should also be quicker as it does not involve a 
# second pipeline.
#
# Support has also been added for 16 character usernames.

$MAC_PROCESS = "afpd";
if ( $^O eq "freebsd" ) {
    $PS_STR    = "-awwxouser,pid,ppid,start,command";
    $MATCH_STR = '(\w+)\s+(\d+)\s+(\d+)\s+([\d\w:]+)';
}
else {
    $PS_STR    = "-ef";
    $MATCH_STR = '\s*(\w+)\s+(\d+)\s+(\d+)\s+\d+\s+([\d\w:]+)';
}
$ASIP_PORT    = "afpovertcp";
$ASIP_PORT_NO = 548;

# Change to 0 if you don't have lsof
$LSOF = 1;
my %mac = ();

if ( $^O eq "freebsd" ) {
    open( SOCKSTAT, "sockstat -4 | grep $MAC_PROCESS | grep -v grep |" );

    while (<SOCKSTAT>) {
        next if ( $_ !~ /$MAC_PROCESS/ );
        $_ =~ /\S+\s+\S+\s+(\d+)\s+\d+\s+[\w\d]+\s+[\d\.:]+\s+([\d\.]+)/;
        my ( $pid, $addr, $host );
        $pid  = $1;
        $addr = $2;
        $host = gethostbyaddr( pack( 'C4', split ( /\./, $addr ) ), AF_INET );
	($host) = ( $host =~ /(^(\d+\.){3}\d+|[\w\d\-]+)/ );
        $mac{$pid} = $host;
    }
    print
      "PID      UID      Username         Name                 Logintime Mac\n";
	close(SOCKSTAT);
}
elsif ( $LSOF == 1 ) {
    open( LSOF, "lsof -i :$ASIP_PORT |" );

    while (<LSOF>) {
        next if ( $_ !~ /$ASIP_PORT/ );
        $_ =~ /\w+\s+(\d+).*->([\w\.-]+).*/;
        my ( $pid, $host );
        $pid  = $1;
        $host = $2;
        ($host) = ( $host =~ /(^(\d+\.){3}\d+|[\w\d\-]+)/ );
        $mac{$pid} = $host;
    }
    print
      "PID      UID      Username         Name                 Logintime Mac\n";
    close(LSOF);
}
else {
    print "PID      UID      Username         Name                 Logintime\n";
}

open( PS, "ps $PS_STR |" ) || die "Unable to open a pipe to ``ps''";

while (<PS>) {
    next if ( $_ !~ /$MAC_PROCESS/ );
    my ( $user, $pid, $ppid, $time, $name, $uid, $t );
    $_ =~ /$MATCH_STR/;
    $user = $1;
    $pid  = $2;
    $ppid = $3;
    $time = $4;

    if ( $ppid != 1 ) {
        ( $t, $t, $uid, $t, $t, $t, $name, $t, $t ) = getpwnam($user);
	($name) = ( $name =~ /(^[^,]+)/ );
        printf "%-8d %-8d %-16s %-20s %-9s %s\n", $pid, $uid, $user, $name,
          $time, $mac{$pid};
    }
}

close(PS);