#!/usr/bin/perl

########################################################################
#
# pmchk Ver 2.1 beta2
#
# Authors      : Gary E. Miller <gem@rellim.com>
# Interpreter  : Perl v5.002
# Portmaster   : ComOS 3.3.1
# Description  : a hack to poll a bunch of portmasters.
#                it reports duplicate users
#                optionally resets the ports of "Hogs"
#                with "-r" resets idle ports
#
#######################################################################
require 'pm.pl';
use Getopt::Std;

$| = 1;

sub usage {
	print 'usage: pmchk [-h] [-v] [-r] [-x minutes] [-H flag]\n';
	print "             -h     help \n";
	print "             -v     verbose\n";
	print "             -r     reset idle modems\n";
	print "             -x nn  flag ports in use longer than nn minutes\n";
	print "                    0 disables hog timer\n";
	print "             -H fl  if fl is non-zero reset Hog ports\n";
	exit;
};

# process options
if ( getopts("-?hrvH:x:") ne 1 ) {
	usage;
}

if ( $opt_h ) {
	usage;
}

# if non-zero, reset ports that have been idle for too long
$Idle_Reset = 0;  # default if no arg

if ( $opt_r ) {
	$Idle_Reset = 1;
	#print "Idle Reset ON\n";
}

# users on more than $Hog_Time in minutes are noted
$Hog_Time = 200;  # default Hog time if no arg

if ( $opt_x ) {
	$Hog_Time = $opt_x;
}

# Hog users are silently disconnected
$Hog_Reset = 0;  # default Hog reset if no arg

if ( $opt_H ) {
	$Hog_Reset = $opt_H;
}

$Verbose = 0;  # default if no arg

if ( $opt_v ) {
	$Verbose = 1;
}

foreach $Host (@All) {

	# @All, $Domain and $Password are set in pm.pl
	portmaster::Connect("$Host", $Password);

	my($Host_id) = $Host;
	$Host_id =~ s/\..*$//; # keep just first part of host name

	# get global vals
	&portmaster::SysGlobal;

	$MaxCnt = $GlobalValue{NUMPORTS};

        CNT_LOOP:
        for ($Cnt = 0; $Cnt <= $MaxCnt; $Cnt++) {
		# for some odd reason, a pm2er puts W1 at the fron and adds on to
		# the normal serial ports
		&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;
		}

    $User =  $PortValue{$Cnt, USERNAME} ;
    $User1 = $User;
   
    # strip service options
    # strip leading P, some ISPs use Puser to specify PPP
    $User1 =~ s/^P//;

    # strip leading S, some ISPs use Puser to specify SLIP
    $User1 =~ s/^S//;

    # strip trailing .ppp, some ISP use user.ppp to specify PPP
    $User1 =~ s/\.ppp$//;

    # strip trailing .shell, some ISP use user.ppp to specify shell
    $User1 =~ s/\.shell$//;

    my($Port) = $PortValue{$Cnt, PORT},
    #printf ">%s< >%s<\n", $User, $User1;

    $Hog = '';
    if ( $User1 ) {
	    $Users{ $User1 }++;
	    my($God) = 0;
            #don't bitch about Gods
            foreach (@Gods) { 
                    if ( $User1 eq $_ ) {
			    $God = 1;
		    }
            }
	    if ( $Users{ $User1 } > 1 ) {
		$Hog = "Dupe ";
                if ( $God == 0 ) {
			open( MAIL, "| mail -s \"Duplicate Logins\" postmaster $User1 ") || die "Can not run mail!";
			print MAIL "Dear \"$User1\":\n\n";
			print MAIL "You are connected multiple times to our dial-in ports!\n";
			print MAIL "This is a violation of your service agreement.  Someone\n";
			print MAIL "has probably stolen your password.  Please change it now\n";
			print MAIL "or we will be forced to do it for you.\n\n";
			print MAIL "If you find yourself unable to log in in the near future\n";
			print MAIL "please call Support to get your new password.\n\n";
			print MAIL "Support\n";
			close MAIL;
                }
	    }
	    if ( $Hog_Time > 0 && $PortValue{$Cnt, STARTTIME} > $Hog_Time ) {
		$Hog .= "Hog";
                if ( $Hog_Reset && $God == 0 ) {
			printf "pmreset $Port $Host\n";
			&portmaster::Command("reset $Port");
		}
            }
    } else {
	  # idle port ?
	  if ( $Idle_Reset && $PortValue{$Cnt, STATUS} eq "IDLE" ) {
		  @Dummy = &portmaster::Command("reset $Port");
		  $Hog = "Reset";
          }
    }

    printf "%.5s-%3s %14.14s%15.15s %12.12s %4d %4d %10d %s\n", 
      $Host_id, 
      $Port,
      $User, $PortValue{$Cnt, FRAMED_ADDR}, 
      # $PortValue{$Cnt, PORT_TYPE},
      $PortValue{$Cnt, STATUS},
      $PortValue{$Cnt, STARTTIME},
      $PortValue{$Cnt, IDLETIME},
      $PortValue{$Cnt, DATA_INPUT},
      $Hog;
  }

  close(portmaster::DS);
}
# comment out this "exit" to dump the Users table for debugging
exit;

$Users{ "Idle" } = $Users{ '' };
$Users{ '' } = '';

print "\n";
foreach $key (sort(keys %Users)) {
	printf "%12s %2d\n", $key, $Users{ $key };
};
