#!/afs/athena/contrib/perl/perl

unshift(@INC, '/afs/athena/user/b/e/bert/PERL/@sys');

require 'utmpx.pl';
require 'utmp.pl';

require 'ctime.pl';

sub usage {
    printf <<"END_of_usage", &UTMP_FILE, &UTMPX_FILE, &WTMP_FILE, &WTMPX_FILE;
usage: $0 [ -h ] [ -u | -w | -f filename ] [ display_toggles ]
	  -h	  show this help message.

          -u	  use utmp file  ( %s ).  this is default.
         -ux	  use utmpx file ( %s ).
	  -w	  use wtmp file  ( %s ).
	 -wx	  use wtmpx file ( %s ).
	  -f	  use specified file in utmp format.
	 -fx	  use specified file in utmpx format.

     diplay_toggles:
	  -a	  set all of the following toggles on.
	  -o	  display offset into the file.
	  -u	  display username (default: on.)
	  -i	  display the inittab id.
	  -l	  display the terminal or line (default: on.)
	  -p	  display the process id.
	  -T	  display entry type. (default: on.)
	  -n	  display the entry type as a number.
	  -e	  display exit status of a process marked as DEAD_PROCESS.
	  -U	  display entry timestamp.
	  -t	  display the entry time, in a human-readable format.
	  -s	  display the session number (with -x only).
	  -r	  display the remote host (with -x only).
END_of_usage
    exit(@_[0] || 1);
}

$print_user = $print_line = $print_type = 1;

ARG:
    while (@ARGV) {
	$arg = shift(@ARGV);
	($arg eq "-h") && &usage("0 but true");

	($arg eq "-u") && (&utmpname (&UTMP_FILE),           next ARG);
	($arg eq "-ux")&& (&utmpxname(&UTMPX_FILE), $ext=1,  next ARG);
	($arg eq "-w") && (&utmpname (&WTMP_FILE),          next ARG);
	($arg eq "-wx")&& (&utmpxname(&WTMPX_FILE), $ext=1,   next ARG);
	($arg eq "-f") && (&utmpname (shift(@ARGV)),         next ARG);
	($arg eq "-fx")&& (&utmpxname(shift(@ARGV)), $ext=1, next ARG);

	($arg eq "-o") && ($print_off =   !$print_off, next ARG);
	($arg eq "-u") && ($print_user =  !$print_user, next ARG);
	($arg eq "-i") && ($print_id =    !$print_id, next ARG);
	($arg eq "-l") && ($print_line =  !$print_line, next ARG);
	($arg eq "-p") && ($print_pid =   !$print_pid, next ARG);
	($arg eq "-T") && ($print_type =  !$print_type, next ARG);
	($arg eq "-n") && ($print_typeN = !$print_typeN, next ARG);
	($arg eq "-e") && ($print_exit  = !$print_exit, next ARG);
	($arg eq "-t") && ($print_time  = !$print_time, next ARG);
	($arg eq "-U") && ($print_timeU = !$print_timeU, next ARG);
	($arg eq "-s") && ($print_sess =  !$print_sess, next ARG);
	($arg eq "-r") && ($print_host =  !$print_host, next ARG);

	($arg eq "-a") &&
	    ($print_off = $print_user = $print_id = $print_line = $print_pid =
	     $print_type = $print_typeN = $print_exit = $print_timeU =
	     $print_sess = $print_host = $print_time = 1, next ARG);

	&usage;
    }

while ((@gue = ($ext ? &getutxent : &getutent) ) && ($#gue > 0)) {
    ($user,$id,$line,$pid,$type,$exit_trm,$exit_exit,$time,$usec,$sess,$host)
	= @gue;
    
    $user =~ s/([\000-\037\200-\377])/sprintf("\\%02X", ord($1))/ge
	if $print_user;
    $id   =~ s/([\000-\037\200-\377])/sprintf("\\%02X", ord($1))/ge
	if $print_id;
    $line =~ s/([\000-\037\177-\377])/sprintf("\\%02X", ord($1))/ge
	if $print_line;
    $host =~ s/([\000-\037\177-\377])/sprintf("\\%02X", ord($1))/ge
	if $print_host;

    printf "%5d ",      $off                  if $print_off;
    printf "%-12s ",    $user                 if $print_user;
    printf "%4s ",      $id                   if $print_id;
    printf "%-15s ",    $line                 if $print_line;
    printf "%5d ",      $pid                  if $print_pid;
    printf "%2d ",      $type                 if $print_typeN;
    printf "%-13s ",    &type2str($type)      if $print_type;
    printf "%5d %5d ",  $exit_trm, $exit_exit if $print_exit;
    printf "%9d ",      $time                 if ($print_timeU && !$ext);
    printf "%9d.%06d ", $time, $usec          if ($print_timeU && $ext);
    if ($print_time) {
	local($ctime) = &ctime($time);
	chop($ctime);
	print " $ctime ";
    }
    printf "%9d ",      $sess                 if ($print_sess && $ext);
    printf "%s ",       $host                 if ($print_host && $ext);
    print "\n";
    $off += ($ext ? $utmpx'struct_length : $utmp'struct_length);
}

sub type2str {
    local($type) = @_;

    ($type == &EMPTY)         && return "EMPTY";
    ($type == &RUN_LVL)       && return "RUN_LVL";
    ($type == &BOOT_TIME)     && return "BOOT_TIME";
    ($type == &OLD_TIME)      && return "OLD_TIME";
    ($type == &NEW_TIME)      && return "NEW_TIME";
    ($type == &INIT_PROCESS)  && return "INIT_PROCESS";
    ($type == &LOGIN_PROCESS) && return "LOGIN_PROCESS";
    ($type == &USER_PROCESS)  && return "USER_PROCESS";
    ($type == &DEAD_PROCESS)  && return "DEAD_PROCESS";
    ($type == &ACCOUNTING)    && return "ACCOUNTING";
    return "???";
}
