diff options
Diffstat (limited to 'mmuegel/libs/mqueue.pl')
-rw-r--r-- | mmuegel/libs/mqueue.pl | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/mmuegel/libs/mqueue.pl b/mmuegel/libs/mqueue.pl new file mode 100644 index 0000000..f425ede --- /dev/null +++ b/mmuegel/libs/mqueue.pl @@ -0,0 +1,215 @@ +;# NAME +;# mqueue.pl - functions to work with the sendmail queue +;# +;# DESCRIPTION +;# Both Get_Queue_IDs and Parse_Control_File are available to get +;# information about the sendmail queue. The cqueue program is a good +;# example of how these functions work. +;# +;# AUTHOR +;# Michael S. Muegel (mmuegel@mot.com) +;# +;# RCS INFORMATION +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/mqueue.pl,v +;# 1.1 of 1993/07/28 08:07:19 + +package mqueue; + +;############################################################################### +;# Get_Queue_IDs +;# +;# Will figure out the queue IDs in $Queue that have both control and data +;# files. They are returned in @Valid_IDs. Those IDs that have a +;# control file and no data file are saved to the array globbed by +;# *Missing_Control_IDs. Likewise, those IDs that have a data file and no +;# control file are saved to the array globbed by *Missing_Data_IDs. +;# +;# If $Skip_Locked is true they a message that has a lock file is skipped +;# and will not show up in any of the arrays. +;# +;# If everything went AOK then $Status is 1; otherwise, $Status is 0 and +;# $Msg tells what went wrong. +;# +;# Globals: +;# None +;# +;# Arguments: +;# $Queue, $Skip_Locked, *Missing_Control_IDs, *Missing_Data_IDs +;# +;# Returns: +;# $Status, $Msg, @Valid_IDs +;############################################################################### +sub main'Get_Queue_IDs +{ + local ($Queue, $Skip_Locked, *Missing_Control_IDs, + *Missing_Data_IDs) = @_; + local (*QUEUE, @Files, %Lock_IDs, %Data_IDs, %Control_IDs, $_); + + # Make sure that the * argument @arrays ar empty + @Missing_Control_IDs = @Missing_Data_IDs = (); + + # Save each data, lock, and queue file in @Files + opendir (QUEUE, $Queue) || return (0, "error getting directory listing of $Queue"); + @Files = grep (/^(df|lf|qf)/, readdir (QUEUE)); + closedir (QUEUE); + + # Create indexed list of data and control files. IF $Skip_Locked is true + # then skip either if there is a lock file present. + if ($Skip_Locked) + { + grep ((s/^lf//) && ($Lock_IDs {$_} = 1), @Files); + grep ((s/^df//) && (! $Lock_IDs {$_}) && ($Data_IDs {$_} = 1), @Files); + grep ((s/^qf//) && (! $Lock_IDs {$_}) && ($Control_IDs {$_} = 1), @Files); + } + else + { + grep ((s/^df//) && ($Data_IDs {$_} = 1), @Files); + grep ((s/^qf//) && ($Control_IDs {$_} = 1), @Files); + }; + + # Find missing control and data files and remove them from the lists of each + @Missing_Control_IDs = sort (grep ((! $Control_IDs {$_}) && (delete $Data_IDs {$_}), keys (%Data_IDs))); + @Missing_Data_IDs = sort (grep ((! $Data_IDs {$_} && (delete $Control_IDs {$_})), keys (%Control_IDs))); + + + # Return the IDs in an appartently random order + return (1, "", keys (%Control_IDs)); +}; + + +;############################################################################### +;# Parse_Control_File +;# +;# Will pase a sendmail queue control file for useful information. See the +;# Sendmail Installtion and Operation Guide (SMM:07) for a complete +;# explanation of each field. +;# +;# The following globbed variables are set (or cleared) by this function: +;# +;# $Sender The sender's address. +;# +;# @Recipients One or more addresses for the recipient of the mail. +;# +;# @Errors_To One or more addresses for addresses to which mail +;# delivery errors should be sent. +;# +;# $Creation_Time The job creation time in time(3) format. That is, +;# seconds since 00:00:00 GMT 1/1/70. +;# +;# $Priority An integer representing the current message priority. +;# This is used to order the queue. Higher numbers mean +;# lower priorities. +;# +;# $Status_Message The status of the mail message. It can contain any +;# text. +;# +;# @Headers Message headers unparsed but in their original order. +;# Headers that span multiple lines are not mucked with, +;# embedded \ns will be evident. +;# +;# In all e-mail addresses bounding <> pairs are stripped. +;# +;# If everything went AOK then $Status is 1. If the message with queue ID +;# $Queue_ID just does not exist anymore -1 is returned. This is very +;# possible and should be allowed for. Otherwise, $Status is 0 and $Msg +;# tells what went wrong. +;# +;# Globals: +;# None +;# +;# Arguments: +;# $Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time, +;# *Priority, *Status_Message, *Headers +;# +;# Returns: +;# $Status, $Msg +;############################################################################### +sub main'Parse_Control_File +{ + local ($Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time, + *Priority, *Status_Message, *Headers) = @_; + local (*Control, $_, $Not_Empty); + + # Required variables and the associated control. If empty at the end of + # parsing we return a bad status. + @REQUIRED_INFO = ('$Creation_Time', 'T', '$Sender', 'S', '@Recipients', 'R', + '$Priority', 'P'); + + # Open up the control file for read + $Control = "$Queue/qf$Queue_ID"; + if (! open (Control)) + { + return (-1) if ((-x $Queue) && (! -f "$Queue/qf$Queue_ID") && + (! -f "$Queue/df$Queue_ID")); + return (0, "error opening $Control for read: $!"); + }; + + # Reset the globbed variables just in case + $Sender = $Creation_Time = $Priority = $Status_Message = ""; + @Recipients = @Errors_To = @Headers = (); + + # Look for a few things in the control file + READ: while (<Control>) + { + $Not_Empty = 1; + chop; + + PARSE: + { + if (/^T(\d+)$/) + { + $Creation_Time = $1; + } + elsif (/^S(<)?([^>]+)/) + { + $Sender = $2; + } + elsif (/^R(<)?([^>]+)/) + { + push (@Recipients, $2); + } + elsif (/^E(<)?([^>]+)/) + { + push (@Errors_To, $2); + } + elsif (/^M(.*)/) + { + $Status_Message = $1; + } + elsif (/^P(\d+)$/) + { + $Priority = $1; + } + elsif (/^H(.*)/) + { + $Header = $1; + while (<Control>) + { + chop; + last if (/^[A-Z]/); + $Header .= "\n$_"; + }; + push (@Headers, $Header); + redo PARSE if ($_); + last if (eof); + }; + }; + }; + + # If the file was empty scream bloody murder + return (0, "empty control file") if (! $Not_Empty); + + # Yell if we could not find a required field + while (($Var, $Control) = splice (@REQUIRED_INFO, 0, 2)) + { + eval "return (0, 'required control field $Control not found') + if (! $Var)"; + return (0, "error checking \$Var: $@") if ($@); + }; + + # Everything went AOK + return (1); +}; + +1; |