#!/usr/bin/perl
#
# By Kevin Kadow (kadow@msg.net), loosely based on Internet Direct's 'pmwho'
# Part of the unpublished 'pmweb' web-based portmaster control software
#
# This program needs 'pm.pl' in the current or a @INC directory in order
# to run. Get it in ftp.rellim.com:/pub/admin/bpmtools2.1.tar.gz
#
# To use as a CGI script, invoke with '-html' (e.g. in ServerSide Include)
# or force $html to 1.

require 'pm.pl';
require 'flush.pl';

#
# Put your portmaster password, you can instead
# put the password in pm.pl and comment out the $Pass= line here.
#
$Pass = $Password;  # get default from pm.pl
#$Pass='mypasswd';

# thanks to ralk@wigand.de for this idea
# or get your password from the cgi-bin argument
# for example http://www.my.com/cgi-bin/pmwho2?passwd
#
# carefull, anyone on the system could use ps to see your password.
#
#$Pass = $ENV(QUERY_STRING);
#$html = 1;  # and force it to output html

# $Domain and @All must be set in pm.pl

$count= $#All +1;

$LongCall=4;	#Flag people who've been on for more than four hours

$| = 1;

#
# Handle command line arguments
#
while($_=shift) {
$Verbose++ if(m/^-v/);
$html++ if(m/^-html/);
}

#
# Print the appropriate header
#
if($html) {
	$date=`date`; chop $date;
	print <<"EOF";
Content-type: text/html
Refresh:  120

<HEAD><TITLE>User List $date</TITLE></HEAD>
<BODY>
<H1>User list for $date</H1>
<PRE>

EOF
	}
else {
	print <<"EOF";
Server  ## Username   Hostname            Status      Idle  Time  Flags
EOF
	}

#
#Cycle through the list of portmasters
#
foreach $Host (@All) {
  portmaster::Connect( "$Host", $Pass);

  my($Host_id) = $Host;
  $Host_id =~ s/\..*$//;  #/ remove domain name part

  # this will fail on pm2er's, on those $cnt = 0 is W1
  CNT_LOOP:
  for ($Cnt = 0; $Cnt <= 30; $Cnt++) {
	local($Flag,$Status,$address,$Machine);
	&portmaster::Who("$Cnt");

        if ( $PortValue{$Cnt,PORT} eq "P0" ) {
		# skip Printer port
		next CNT_LOOP;
	}

        if ( $PortValue{$Cnt,PORT} eq "W1" ) {
		# skip WAN port
		next CNT_LOOP;
	}
	$Ports++;
	next if("IDLE" eq $PortValue{$Cnt,STATUS});
	$Used++;

	
	#if($PortValue{$Cnt, PORT_TYPE} ne "Login/Netwrk" ) {
	#warn "Port $Cnt on $Host is not configured for Login/Netwrk!!\n";
	#};

	$User=$PortValue{$Cnt, USERNAME};
	 if(($Users{$User}++) >1) {
		#
		#Logged on more than once!
		#
		$Flag="x".$Users{$User};
		}
	$Status=$PortValue{$Cnt, STATUS},
	$address=$PortValue{$Cnt,FRAMED_ADDR};
	if($address eq "0.0.0.0") {
		#
		# Addr9 is just a guess.
		#
		$address=$PortValue{$Cnt,Addr9};
		}
	else {
		$Status="SLIP/PPP";
		$SLIP++;
		}

	#
	# Convert their time online to human readable, flag long calls
	#
	$time=$PortValue{$Cnt, STARTTIME};
	$hours=int($time / 60);
	$Flag.="!" if($hours >$LongCall);
	$minutes= $time % 60;

        # huh?
	unless($Machine=$lookup{$address}) {
	$Machine=$address unless($Machine=&address2name($address));
	$Machine=~ s/$domain//;
	$lookup{$address}=$Machine;
	}


	$Total{$Machine}++ unless($Status eq "SLIP/PPP");

	printf "%8.8s-%3s %-10s %-15s %15s %4d %2d:%2.2d  %s\n", 
        $Host_id,
	$PortValue{$Cnt, PORT},
	$User, $Machine,
	$Status,
	 $PortValue{$Cnt, IDLETIME},$hours,$minutes,$Flag;
  }
  close(portmaster::DS);
}

#
# Print the trailer 
#
print "\n";
print "<HR>" if($html);
foreach $Machine (keys(%Total)) {
	if($html) {
		print "<B>${Machine}</B>: $Total{$Machine}<BR>\n";
		}
	else {
		print "$Machine:$Total{$Machine} "
		}
	}
if($html) {
	print "<B>SLIP</B>: ${SLIP}<BR>\n";
	print "Total $Used of $Ports\n";
	}
else {
	print "SLIP/PPP: $SLIP = $Used/$Ports\n";
	}
exit;


sub address2name {
	local($addr,@bytes)=@_;
	local($name,$aliases,$addrtype,$length,@addrs);
	($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($addr);
	($name,$aliases,$addrtype,$length,@addrs) = gethostbyaddr($addrs[0],$addrtype);
	return($name);
	}

