#!/usr/local/bin/perl 
#
# /usr/local/bin/sortu  - sort and count users by login name
#                       - display the terminal info as well
#                       - only display folks with more than a certain
#                       - number of logins (4 by default)
#
# Author: Jim Wildman, 3X HealthCare Solutions Group 
# Date: 12/23/1999
# Revised: 2/10/2000    - Added comments, etc
#
# This code is released under the GNU Software License.  See
# http://www.gnu.org for details

use Getopt::Std;

getopts('hsl:') || die "Usage: sortu [-h] | [-s] [-l n]\n'n' defaults to 5\n"; 

# the 's' option is to generate only the summary information
if($opt_h){
        printf("Usage: sortu [-h] | [-s] [-l n] \n");
        printf("        Sort and count logins by userid\n");
        printf("        -h display this help message\n");
        printf("        -s display summary counts only\n");
        printf("        -l n set the cutoff level for display of logins\n");
        printf("             (defaults to 5 or more)\n\n");
        exit;
}
# the 'l' option allows us to set the threshold level for display and 
# summarization
($opt_l > 0) ? ($num_logins = $opt_l) : ($num_logins = 5) ;

# slurp up the passwd file to get user names.
# sure would be nice to have complete info in here!!
# We could do this with the getpw* functions, but I already have this
# done.
@pwlist = `cat /etc/passwd` ;
foreach $item (@pwlist) {
        chomp $item ;
        ($logname,$f1,$f2,$f3,$username) = split(/\:/,$item) ;

        # all we are after is the login id and real user name
        $uname{$logname} = $username ;
}

# Get our list of users
# This is where the big delay in the program is.  'who -u' takes a
# couple of seconds
# The output looks like...
# brcmwb1    pty/ttyb9    Feb 10 06:59  0:52  22217  brcdtc21
# brckdv1    pty/ttybc    Feb 10 06:27  0:03  14495  b0gw6238
# brcshp2    pty/ttybd    Feb 10 08:13  0:15   6909  brcdtc13 
#
@users = `who -u`;

# For each user analyze the lines.
foreach $item (@users) {
        chomp $item;

        # split the who output.  All we want is the first field 
        ($user) = split(/\s+/,$item) ;

        # count the instances of each user
        $total{$user}++ ;

        # count the total number of logins so far
        $tot_logins++ ;

        # store the lines for output
        # we strip off the login name so it doesn't get repeated
        if ($total{$user} == 1) {
                $myterm{$user} = sprintf("\t%s\n", substr($item, 11)) ;
        }
        else {
                # this builds up a list with embedded newlines and tabs
                $myterm{$user} = sprintf("%s\t%s\n", $myterm{$user}, 
                        substr($item, 11)) ;
        }
}
# This uses the defined subroutine to sort by the count
foreach $i (sort by_count (keys %total)) {

        # total users
        $tot_users++;

        # This is limited by the value given with the -l option
        if($total{$i} >= $num_logins) {

           # If the summary flag is set, don't print all the details
           # But we still have to do this to roll up the subtotals right
           if($opt_s == 0) {
                printf("%d %s %s\n%s", $total{$i}, $i, $uname{$i},
                $myterm{$i});
           }
           $totgethannumlogins++ ;
    }
}

# This is the 'summary' block
printf("\t %d total logins\n",$tot_logins) ;
printf("\t %d distinct users with %s having %s or more logins\n", 
        $tot_users, $totgethannumlogins, $num_logins) ;

# Define our own sort routine to sort by the second element (the count)
sub by_count {
        return $total{$a} <=> $total{$b} ;
}