#!/usr/local/bin/perl
##--------------------------------------------------------------------------##
##  File:
##      $Id: mh-month-pack,v 1.4 2002/09/15 03:33:08 ehood Exp $
##  Description:
##      See POD below or run program with -man option.
##--------------------------------------------------------------------------##
##  Copyright (C) 2002	    Earl Hood <earl@earlhood.com>
##
##  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
##  (at your option) any later version.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##
##  You should have received a copy of the GNU General Public License
##  along with this program; if not, write to the Free Software
##  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
##  02111-1307, USA
##--------------------------------------------------------------------------##

package MHArc::mh_month_pack;

BEGIN { die qq/CGI use FORBIDDEN!\n/ if (defined($ENV{'GATEWAY_INTERFACE'})); }

use Pod::Usage;
use Getopt::Long;

use constant SCAN_FORMAT_STR =>
    '%(msg) %<{x-mharc-packed}*%>%(year{date})-%02(mon{date})-%02(mday{date})';

my $debug = 0;
my $verbose = 0;
my $noop = 0;
my $noanno = 0;
my $all = 0;

my $outdir = '.';
my $yearly = 0;

MAIN: {
  # Grap command-line options
  GetOptions(
    "all!"        => \$all,
    "debug!"      => \$debug,
    "n!"          => \$noop,
    "noanno!"     => \$noanno,
    "outdir=s"	  => \$outdir,
    "verbose!"    => \$verbose,
    "yearly!"     => \$yearly,

    "help"        => \$help,
    "man"         => \$man
  ) || usage(0);
  usage(1) if $help;
  usage(2) if $man;

  $verbose = 1  if $noop;
  $verbose = 1  if $debug;

  my @folders = @ARGV;
  if (@folders <= 0) {
    die qq/Error: No folders specified\n/;
  }

  # Trim in leading +'s specified
  foreach (@folders) {
    s/^\+//;
  }

  # Save off current folder
  my $curfolder = `folder -fast`;
  chomp $curfolder;
  print qq/Current folder is "$curfolder"\n"/  if $verbose;

  local(*SCAN);
  my $folder;
  foreach $folder (@folders) {
    print qq/Processing folder "$folder"...\n/  if $verbose;

    # Open read pipe to scan to get message number and date for each
    # message.
    if (!open(SCAN, qq/scan +$folder -format '/.SCAN_FORMAT_STR.qq/'|/)) {
      warn qq/Warning: Non-zero exit status from "scan": $?\n/;
      next;
    }

    my($msg, $date, $rest);
    my($year, $mon, $day);
    my($mbox, $packed);

    # Read scan output and copy messages into mailbox files
    while (<SCAN>) {
      next  unless /^\s*\d/;

      print $_  if $debug;
      chomp;

      ($msg, $date, $rest) = split(' ', $_, 3);
      $packed = $date =~ s/\*//;

      if (!$all && $packed) {
	print qq/Skipping message "$msg", already packed.\n/;
	next;
      }

      $date += 1900  if $date < 1900;	# just incase
      ($year, $mon, $day) = split('-', $date, 3);

      if ($yearly) {
	$mbox = $year;
      } else {
	$mbox = "$year-$mon";
      }

      # Pre-create the mbox file if it does not exist: prevents
      # packf from prompting to create.
      if (! -e $mbox) {
	run_cmd("touch $outdir/$mbox");
      }

      # Have packf actually append message to mailbox file.
      if (run_cmd("packf -mbox -file $outdir/$mbox $msg")) {
	warn qq/Warning: Non-zero exit status from "packf": $?\n/;
	next;
      }

      # Annotate message that it has been processed.
      if (!$noanno) {
	if (run_cmd("anno -component x-mharc-packed -inplace -nodate ".
		    "-text '1' $msg")) {
	  warn qq/Warning: Non-zero exit status from "anno": $?\n/;
	  next;
	}
      }
    }

    close(SCAN);
  }

  # Restore current folder
  run_cmd("folder +$curfolder");

} # End: MAIN


sub run_cmd {
  if ($verbose) {
    print @_, "\n";
  }
  return 0  if ($noop);
  system(@_);
}

sub usage {
  require Pod::Usage;
  my $verbose = shift;
  if ($verbose == 0) {
    Pod::Usage::pod2usage(-verbose => $verbose);
  } else {
    my $pager = $ENV{'PAGER'} || 'more';
    local(*PAGER);
    my $fh = (-t STDOUT && open(PAGER, "|$pager")) ? \*PAGER : \*STDOUT;
    Pod::Usage::pod2usage(-verbose => $verbose,
			  -output  => $fh);
  }
}


##--------------------------------------------------------------------------##
__END__

=head1 NAME

mh-month-pack - Copy MH/nmh messages into monthly mailbox files.

=head1 SYNOPSIS

  mh-month-pack [options] folder ...

=head1 DESCRIPTION

This program copies MH/nmh messages into mailbox files.  By default,
monthly mailbox files are created with filenames of I<YYYY-MM> format.
If the C<-yearly> option is specified, than messages will be split
into yearly, I<YYYY>, files.  If a mailbox file already exists,
messages will be appended to it.

Each MH/nmh process will be annotated inorder to mark the message as
having been processed, unless the C<-noanno> option is specified.
The annotation allows this program to reprocess folders multiple
times and to skip messages that have been packed before.

This program is provided as part of mharc to provide the ability
to import MH/nmh messages into mharc archives.  This program could
be used for sites that have an existing MH/nmh filtering system
inplace and want to usage mharc to generate web-based archives.
This program can be used instead of L<filter-spool|filter-spool> to
move incoming messages into the raw message archive before calling
L<web-archive|web-archive>.

=head1 OPTIONS

Any non-option argument is treated as an MH/nmh folder to process.
Folders are specified in the same manner as in MH/nmh commands.

=over

=item C<-all>

Force packing of all messages, even if some messages are marked as
processed.

=item C<-debug>

Like C<-verbose>, but prints out more.

=item C<-help>

Print out help message.

=item C<-man>

Print out the manpage.

=item C<-n>

Just echo what would be done, but do not do it.  This is handy
to verify what will be done before actually doing it for real.

=item C<-noanno>

Do not annotate messages that have been processed.  By default, this
program will annotate the messages via the anno(1) command to mark
messages as being processed.  Therefore, if the folder is processed
again in the future, the message will be skipped.

=item C<-outdir> I<directory>

Directory to place mailbox files.  If not specified, the
current working directory is used.

=item C<-verbose>

Print status of what is going on.

=item C<-yearly>

Generate yearly-based mailbox files instead of monthly-based.

=back

=head1 DEPENDENCIES

This program requires that the following MH/nmh commands are in
your search path: C<anno(1)>, C<folder(1)>, C<scan(1)>, C<packf(1)>.

=head1 LIMITATIONS

=over

=item *

Pre-existing gzipped mailbox files are not recognized.

=back

=head1 VERSION

$Id: mh-month-pack,v 1.4 2002/09/15 03:33:08 ehood Exp $

=head1 AUTHOR

Earl Hood, earl@earlhood.com

This program is part of the mharc archiving system and comes with
ABSOLUTELY NO WARRANTY and may be copied only under the terms of
the GNU General Public License, which may be found in the mharc
distribution.

=cut

