#!/usr/local/ustart/bin/suidperl

# NAME
#    cqueue - check sendmail queue for problems
#
# SYNOPSIS
#    Type cqueue -usage
#
# AUTHOR
#    Michael S. Muegel <mmuegel@mot.com>
#
# RCS INFORMATION
#    mmuegel
#    /usr/local/ustart/src/mail-tools/dist/foo/src/cqueue,v 1.1 1993/07/28 08:09:02 mmuegel Exp

# So that date.pl does not yell (Domain/OS version does a ``)
$ENV{'PATH'}    = "";

# A better getopts routine
require "newgetopts.pl";
require "timespec.pl";
require "mail.pl";
require "date.pl";
require "mqueue.pl";
require "strings1.pl";
require "elapsed.pl";

($Script_Name = $0) =~ s/.*\///;
         
# Some defaults you may want to change
$DEF_TIME	= "2h";
$DEF_QUEUE      = "/usr/spool/mqueue";
$DEF_COLUMNS	= 80;
$DATE_FORMAT    = "%r %D";

# Constants that probably should not be changed
$USAGE          = "Usage: $Script_Name [ -abdms ] [ -q queue-dir ] [ -t time ] [ -u user ] [ -w width ]\n";
$VERSION        = "${Script_Name} by mmuegel; 1.1 of 1993/07/28 08:09:02";
$SWITCHES       = "abdmst:u:q:w:";
$SPLIT_EXPR	= '\s,\.@!%:';
$ADDR_PART_EXPR	= '[^!@%]+';

# Let getopts parse for switches
$Status = &New_Getopts ($SWITCHES, $USAGE);
exit (0) if ($Status == -1);
exit (1) if (! $Status);

# Check args 
die "${Script_Name}: -u only valid with -m\n" if (($opt_u) && (! $opt_m));
die "${Script_Name}: -a not valid with -t option\n" if ($opt_a && $opt_t);
$opt_u = getlogin || (getpwuid ($<))[0] || $ENV{"USER"} || die "${Script_Name}: can not determine who you are!\n" if (! $opt_u);

# Set defaults
$opt_t = "0s" if ($opt_a);
$opt_t = $DEF_TIME if ($opt_t eq "");
$opt_w = $DEF_COLUMNS if ($opt_w eq "");
$opt_q = $DEF_QUEUE if ($opt_q eq "");
$opt_s = $opt_d = 1 if (! ($opt_s || $opt_d));

# Untaint the users to mail to
$opt_u =~ /^(.*)$/;
$Users = $1;

# Convert time option to seconds and seconds to elapsed form
die "${Script_Name}: $Msg\n" if (! (($Status, $Msg, $Seconds) = &Time_Spec_To_Seconds ($opt_t))[0]);
$Elapsed = &Seconds_To_Elapsed ($Seconds, 1);
$Time_Info = " longer than $Elapsed" if ($Seconds);

# Get the current time
$Current_Time = time;
$Current_Date = &date ($Current_Time, $DATE_FORMAT);

($Status, $Msg, @Queue_IDs) = &Get_Queue_IDs ($opt_q, 1, @Missing_Control_IDs,
   @Missing_Data_IDs);
die "$Script_Name: $Msg\n" if (! $Status);

# Yell about missing data/control files?
if ($opt_b)
{

   $Report = "\nMessages missing control files:\n\n   " . 
             join ("\n   ", @Missing_Control_IDs) . 
             "\n" 
      if (@Missing_Control_IDs);

   $Report .= "\nMessages missing data files:\n\n   " . 
              join ("\n   ", @Missing_Data_IDs) . 
              "\n"
      if (@Missing_Data_IDs);
};

# See if any mail messages are older than $Seconds
foreach $Queue_ID (@Queue_IDs)
{
   # Get lots of info about this sendmail message via the control file
   ($Status, $Msg) = &Parse_Control_File ($opt_q, $Queue_ID, *Sender, 
      *Recipients, *Errors_To, *Creation_Time, *Priority, *Status_Message, 
      *Headers);
   next if ($Status == -1);
   if (! $Status)
   {
      warn "$Script_Name: $Queue_ID: $Msg\n";
      next;
   };

   # Report on message if it is older than $Seconds
   if ($Current_Time - $Creation_Time >= $Seconds)
   {
      # Build summary by host information. Keep track of each host destination
      # encountered.
      if ($opt_s)
      {
         %Host_Map = ();
         foreach (@Recipients)
         {
	    if ((/@($ADDR_PART_EXPR)$/) || (/($ADDR_PART_EXPR)!$ADDR_PART_EXPR$/))
            {
	       ($Host = $1) =~ tr/A-Z/a-z/;
               $Host_Map {$Host} = 1;
	    }
	    else
	    {
	       warn "$Script_Name: could not find host part from $_; contact author\n";
	    };
         };

         # For each unique target host add to its stats
         grep ($Host_Queued {$_}++, keys (%Host_Map));

         # Build summary by message information.
         $Message_Queued {$Status_Message}++ if ($Status_Message);
      };

      # Build long report information for this creation time (there may be
      # more than one message created at the same time)
      if ($opt_d)
      {
         $Creation_Date = &date ($Creation_Time, $DATE_FORMAT);
         $Recipient_Info = &Format_Text_Block (join (", ", @Recipients), 
	    "   Recipient: ", 1, 0, $opt_w, $SPLIT_EXPR);
         $Time_To_Report {$Creation_Time} .= <<"EOS";

   ID:        $Queue_ID
   Date:      $Creation_Date
   Sender:    $Sender
$Recipient_Info
EOS

         # Add the status message if available to long report
         if ($Status_Message)
         {
	    $Time_To_Report {$Creation_Time} .= &Format_Text_Block ($Status_Message, 
   	       "   Status:    ", 1, 0, $opt_w, $SPLIT_EXPR) . "\n";
         };
      };
   };

};

# Add the summary report by target host?
if ($opt_s)
{
   foreach $Host (sort (keys (%Host_Queued)))
   {
      $Host_Report .= &Format_Text_Block ($Host, 
         sprintf ("   %-9d   ", $Host_Queued{$Host}), 1, 0, $opt_w,
         $SPLIT_EXPR) . "\n";
      $Num_Hosts += $Host_Queued{$Host};
   };
   if ($Host_Report)
   {
      chop ($Host_Report);
      $Report .= &Format_Text_Block("\nSummary of messages in queue$Time_Info by destination host:\n", "", 0, 0, $opt_w);

      $Report .= <<"EOS";

   Number of
   Messages    Destination Host
   ---------   ----------------
$Host_Report
   ---------
   $Num_Hosts
EOS
   };
};

# Add the summary by message report?
if ($opt_s)
{
   foreach $Message (sort (keys (%Message_Queued)))
   {
      $Message_Report .= &Format_Text_Block ($Message, 
         sprintf ("   %-9d   ", $Message_Queued{$Message}), 1, 0, $opt_w, 
         $SPLIT_EXPR) . "\n";
      $Num_Messages += $Message_Queued{$Message};
   };
   if ($Message_Report)
   {
      chop ($Message_Report);
      $Report .= &Format_Text_Block ("\nSummary of messages in queue$Time_Info by status message:\n", "", 0, 0, $opt_w);

      $Report .= <<"EOS";

   Number of
   Messages    Status Message
   ---------   --------------
$Message_Report
   ---------
   $Num_Messages
EOS
   };
};

# Add the detailed message reports?
if ($opt_d)
{
   foreach $Time (sort { $a <=> $b} (keys (%Time_To_Report)))
   {
      $Report .= &Format_Text_Block ("\nDetail of messages in queue$Time_Info sorted by creation date:\n","", 0, 0, $opt_w) if (! $Detailed_Header++);
      $Report .= $Time_To_Report {$Time};
   };
};

# Now mail or print the report
if ($Report)
{
   $Report .= "\n";
   if ($opt_m)
   {
      ($Status, $Msg) = &Send_Mail ($Users, "sendmail queue report for $Current_Date", $Report, 0);
      die "${Script_Name}: $Msg" if (! $Status);
   }

   else
   {
      print $Report;
   };

};

# I am outta here...
exit (0);
