#!@{PERL_PATH}
#
# $Id: q,v 2.2 1994/11/29 09:25:04 remy Exp $
#
# remy@ccs.neu.edu
# 27 June 1994
#
# Copyright (C) 1994 by Remy Evard
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.

#
# A copy of the license may be found in docs/license of the source
# distribution.
#

require "ctime.pl";
($program = $0)  =~ s:.*/::;

$resolved_dir = "@{CODE_RESOLVED_DIR}";
$active_dir   = "@{CODE_ACTIVE_DIR}";
$error_dir    = "@{CODE_ERROR_DIR}";

$use_dir = $active_dir;

$time=time();
$=   = 10000;

$no_low = 1;
$reverse = 0;
$do_merged = 0;
$prio_match = ".*";
$status_match = ".*";
$owner_match = "^.*$";
$owner_changed = 0;
$user_match = ".*";
$see_all = 1;
$sort_by_time = 0;

$bottom = 0;     # lowest req number to print
$top = -1;       # highest req number to print (-1 means highest)
$offset = 0;     # number to print from first or last

&parse_args();

if($see_all == 0) {
  if(($user = (getpwuid($<))[0]) =~ /^\s*$/) {
    print STDERR "unable to get your login name";
    exit(1);
  }
  $user_match = "^$user$";
  $^ = statustop;
  $~ = status;
  if(($top == $bottom) != 0) {
    &show($top);
    exit(0);
  }
}

if($sort_by_time) {
  @allfiles = &read_files($use_dir);
  %modified = &get_time_of_files($use_dir, @allfiles);
  @allfiles = (sort bytime @allfiles);
} else {
  @allfiles = (sort revnumerically &read_files($use_dir));
}

if(!$offset) {
  $top = time() if($top == -1);
  foreach $n (@allfiles) {
    push(@newlist, $n) if($n <= $top && $n >= $bottom);
  }
  @allfiles = @newlist;
}

@allfiles = reverse @allfiles if($reverse);
$count = 0;

file:
foreach $f (@allfiles) {
  last if($count && $count == $offset);

  &read_file("$use_dir/$f");

  $was_merged = $merged = 0;
  while($merged = &get_header("x-request-merged")) {
    if($do_merged) {
      $was_merged = $merged;
      $merged =~ s:\s*::g;
      &read_file("$use_dir/$merged");
    } else {
      next file;
    }
  }

  $own{$f}  = &get_header("x-request-owner");
  $req{$f}  = &get_header("x-request-user");
  $prio{$f} = &get_header("x-request-priority");
  $stat{$f} = $was_merged ? "> $was_merged" : &get_header("x-request-status");
  $sub{$f}  = &get_header("subject");
  $date{$f} = &get_header("x-request-date");
  $noti{$f} = &get_header("x-request-notified");

  if($req{$f} =~ /<(.*)>/) {
    $req{$f} = $1;
  } elsif ($req{$f} =~ /\((.*)\)>/) {
    $req{$f} = $1;
  }

  next if($no_low && $prio{$f} eq "low");
  next if($prio{$f} !~ /$prio_match/);
  next if($stat{$f} !~ /$status_match/);
  next if($own{$f} !~ /$owner_match/);
  next if($req{$f} !~ /$user_match/);

  ($subject{$f} = $sub{$f}) =~ s:@{PERL_TAGLINE_COMPARE}\s*::;

  if($no_low) {
    $priosym{$f} = " ";
  } else {
    $priosym{$f} = ($prio{$f} eq "low" ? "." : "o");
  }
  $priosym{$f} = "*" if($prio{$f} =~ /high/);
  
  $date{$f} = &date_diff(&getseconds(&get_header("x-request-date")), $time);
  $notified = $header{"x-request-notified"};
  if($notified =~ /^\s*$/) {
    $notified{$f} = "";
  } else {
    $not_sec = &getseconds($notified);
    $notified{$f} = &date_diff($not_sec, $time);
  }

  write;
  $count++;
}

if($see_all == 0) {
  print "--------------------------------------------------------------------------\n";
  print "Please mail all requests to \"@{MAILING_LIST_NAME}\", not to individuals.\n";
  print "Run `@{STATUS} <number>' the see the details of a specific request.\n";
}

exit(0);

# ===========================================================================
# Subs
# ===========================================================================

sub revnumerically {$b <=> $a;};

sub bytime {$modified{$a} <=> $modified{$b};};


sub get_header {
  local($head) = @_;
  $head =~ tr:A-Z:a-z:;
  $header{$head};
}


sub read_file {
  local($file)= @_;

  open(FOO, "<$file");
  
  %header=();
  while(<FOO>) {
    chop;
    last if(/^\s*$/);
    if(/^(\S*):\s*(.*)\s*/) {
      ($h = $1) =~ tr:A-Z:a-z:;
      $header{$h} = $2;
    }
  }
  close(FOO);
}


sub read_files {
  local($dir) = @_;
  local(@allfiles, $f);

  opendir(DIR, $dir);
  @allfiles = grep(/^\d+$/, readdir(DIR));
  closedir(DIR);

  @allfiles;
}

sub get_time_of_files {
  local($dir, @allfiles) = @_;
  local($f, %modified);

  foreach $f (@allfiles) {
    $modified{$f} = -M "$dir/$f";
  }

  %modified;
}


sub date_diff {
  local($old, $new) = @_;
  local($diff, $minute, $hour, $day, $week, $month, $year, $s, $string);

  $diff = $new - $old;
  
  $minute = 60;
  $hour   = 60 * $minute;
  $day    = 24 * $hour;
  $week   = 7 * $day;
  $month  = 4 * $week;
  $year   = 356 * $day;
  
  if($diff < $minute) {
    $s=$diff;
    $string="sec";
  } elsif($diff < $hour) {
    $s = int($diff/$minute);
    $string="min";
  } elsif($diff < $day) {
    $s = int($diff/$hour);
    $string="hr";
  } elsif($diff < $week) {
    $s = int($diff/$day);
    $string="day";
  } elsif($diff < $month) {
    $s = int($diff/$week);
    $string="wk";
  } elsif($diff < $year) {
    $s = int($diff/$month);
    $string="mth";
  } else {
    $s = int($diff/$year);
    $string="yr";
  }
  return "$s $string";
} 


sub getseconds {
  local($datestr) = @_;
  local($sec);

  # Look for the number of seconds to be in parenthesis on the date line.
  if($datestr =~ /\((\d+)\)/) {
    return $1;
  }

  # Otherwise, parse the date string.
  if(!(($datestr =~ /[A-Z][A-Z][A-Z]/) || ($datestr =~ /-\d\d\d/))) {
    $datestr .= " EDT";
  }
  $datestr =~ s:\(.*\)::;
  open(FOO, "@{CODE_GETDATE} \"$datestr\"|") || die "Can't run getdate";
  chop($sec = <FOO>);
  close(FOO);

  $sec;
}


sub parse_args {
  for($i=0;$i<=$#ARGV;$i++) {
    if($ARGV[$i] eq "-runbyuser") {
      $see_all = 0;
      next;
    }
    if($ARGV[$i] =~ /:(\d+)/) {
      $offset = $1;
      next;
    }
    if($ARGV[$i] =~ /(\d+):/) {
      $offset = $1;
      next;
    }
    if($ARGV[$i] =~ /^(\d+)-(\d+)/) {
      $bottom = $1;
      $top = $2;
      if($top < $bottom) {
	$temp = $top;
	$top = $bottom;
	$bottom = $temp;
      }
      next;
    }
    if($ARGV[$i] =~ /^(\d+)-/) {
      $bottom = $1;
      next;
    }
    if($ARGV[$i] =~ /^-(\d+)/) {
      $top = $1;
      next;
    }
    if($ARGV[$i] =~ /^(\d+)/) {
      $top = $bottom = $1;
      $no_low = 0;
      next;
    }
    if($ARGV[$i] eq "-prio") {
      $prio_match = $ARGV[++$i];
      if($prio_match eq "all") {
	$prio_match = ".*";
      }
      $no_low = 0;
      next;
    }
    if($ARGV[$i] =~ "^-op") {
      $status_match = "open";
      next;
    }
    if($ARGV[$i] =~ "^-ow") {
      if((!$ARGV[$i+1]) || $ARGV[$i+1] =~ /^-/) {
        if(($owner_match = (getpwuid($<))[0]) =~ /^\s*$/) {
          print STDERR "unable to get your login name";
          exit(1);
        }
        $owner_match = "^$owner_match$";
      } else {
        $owner_match = $owner_changed ? "^$ARGV[++$i]\$|$owner_match" 
  				      : "^$ARGV[++$i]$" ;
        $owner_changed = 1;
        next;
      }
    }
    if($ARGV[$i] =~ "^-us") {
      $user_match = $ARGV[++$i];
      next;
    }
    if($ARGV[$i] =~ "^-st") {
      $status_match = $ARGV[++$i];
      next;
    }
    if($ARGV[$i] =~ "^-un") {
      $owner_match = $owner_changed ? "^\\s*\$|$owner_match" 
				    : "^\\s*$" ;
      $owner_changed = 1;
      next;
    }
    if($ARGV[$i] =~ "-res") {
      $use_dir = $resolved_dir;
      next;
    }
    if($ARGV[$i] eq "-r") {
      $reverse = 1;
      next;
    }
    if($ARGV[$i] eq "-t") {
      $sort_by_time = 1;
      next;
    }
    if($ARGV[$i] =~ "^-m") {
      $do_merged = 1;
      $prio_match = ".*";
      $no_low = 0;
      next;
    }
    if($ARGV[$i] eq "-" || $ARGV[$i] eq "-help" || $ARGV[$i] eq "-usage") {
     &usage();
     exit(0);
    }
  }  
}

sub usage {
  print "usage: $program <options>\n";
  print "       Where options are any of:\n";
  print "          -r               prints oldest requests first\n";
  print "          -t               prints most recently modified requests first\n";
  print "          -prio all        prints all of them regardless of priority\n";
  print "          -prio <prio>     prints all whose priority match <prio>\n";
  print "          -owner [<login>] prints all requests owned by <login>\n";
  print "          -user <login>    prints all requests made by <user>\n";
  print "          -open            prints only the open requests\n";
  print "          -status <status> prints only <status> requests\n";
  print "          -unowned         prints only the un-taken requests\n";
  print "          -resolved        prints the resolved requests\n";
  print "          <num>-<num>      print only requests in the number range\n";
  print "          <num>            print only request <num>\n";
  print "          :<num>           print a total of <num> requests\n";
  print "\n";
  print "       Without options, it prints all non low priority requests.\n";
  print "\n";
}

sub show {
  local($show) = @_;

  ($active_file, $resolve_file) = &get_file_names($show);
  if(&active_request($active_file)) {
    &read_file($active_file);
    if(&get_header("x-request-user") eq $user) {
      open(FOO, $active_file) || die "Unable to open $active_file";
      while(<FOO>) {
        print;
      }
      close(FOO);
    } else {
      print "Request number $show is not available.\n";
    }
  } elsif(&resolved_request($resolved_file)) {
    &read_file($resolved_file);
    if(&get_header("x-request-user") eq $user) {
      open(FOO, $resolved_file) || die "Unable to open $resolved_file";
      while(<FOO>) {
        print;
      }
      close(FOO);
    } else {
      print "Request number $show is not available.\n";
    }
  } else {
    print "Request number $show is not available.\n";
  }
}  

sub get_file_names {
  # Given a request number, return the name of the associated active file
  # and resolved file.  
  # Don't do any checking for existence, but should probably make sure
  # the files are in reasonable places for security reasons.
  #
  local($num) = @_;
  ("$active_dir/$num", "$resolved_dir/$num");
}
  

sub resolved_request {
  local($file) = @_;
  (-f $file);
}


sub active_request {
  local($file) = @_;
  (-f $file);
}



format top =
Req # ! Owner    Age    Told   Status  User       Subject
----- - -------- ------ ------ ------- ---------- ---------------------------
.

format STDOUT =
@#### @ @<<<<<<< @>>>>> @>>>>> @<<<<<< @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<
$f, $priosym{$f}, $own{$f}, $date{$f}, $notified{$f}, $stat{$f}, $req{$f}, $subject{$f}
.

format statustop =
Req # ! Owner    Age     Status   Subject
----- - -------- ------- -------- ----------------------------------------
.

format status =
@#### @ @<<<<<<< @<<<<<< @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$f, $priosym{$f}, $own{$f}, $date{$f}, $stat{$f}, $subject{$f}
.
