#! /usr/pkg/bin/perl
################################################################
###
###			       immknmz
###
### Author:  Shuichi Kitaguchi <kit@Mew.org>
###	Internet Message Group <img@mew.org>
### Created: Sep 23, 1999
### Revised: Feb 15, 2010
###

BEGIN {
    use lib '/usr/pkg/lib/perl5/vendor_perl/5.40.0';
};

$Prog = 'immknmz';
my $VERSION_DATE = "20161010";
my $VERSION_NUMBER = "153";
my $VERSION = "${Prog} version ${VERSION_DATE}(IM${VERSION_NUMBER})";
my $VERSION_INFORMATION = "${Prog} (IM ${VERSION_NUMBER}) ${VERSION_DATE}
Copyright (C) 1999 IM developing team
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
";

use IM::Config;
use IM::Util;
use IM::Folder;
use IO::File;
use strict;
use vars qw($Prog $EXPLANATION @OptConfig
	    @opt_src $opt_gcnmz $opt_timestamp $opt_verbose
	    $opt_help $opt_version);

$EXPLANATION = "$VERSION
make namazu index for mail folders

Usage: $Prog [OPTIONS] [FOLDERS]
";

@OptConfig = (
    'src;F@;;'    => 'Set source folders (Mail/.folders file is used by default)',
    'gcnmz;b;;'   => "Use gcnmz after mknmz (Garbage Collection for Namazu index)",
    'timestamp;b;;' => "Use checking time stamp",
    'verbose;b;;' => "With verbose messages",
    'help;b;;'    => "Display this help and exit",
    'version,V;b;;' => "Output version information and exit",
    );

init_opt(\@OptConfig);
read_cfg();
read_opt(\@ARGV);
print("${VERSION_INFORMATION}") && exit $EXIT_SUCCESS if $opt_version;
help($EXPLANATION) && exit $EXIT_SUCCESS if $opt_help;

my $lockdir = namazu_lock_path();
if ($lockdir) {
    unless (mkdir($lockdir, 0700)) {
	print STDERR "$Prog: cannot create lock directory: $lockdir.\n";
	$lockdir = "";
	exit $EXIT_ERROR;
    }
}
END {
    if ($lockdir && -d $lockdir) {
	rmdir $lockdir;
    }
}

my $mailpath = mail_path() . "/";
my $namazupath = namazu_path() . "/" . mail_dir() . "/";
my $mknmz_incfile = mknmz_include_file();
if (! -f $mknmz_incfile) {
    $mknmz_incfile = "";
}
my $mknmz_args = "-q";
$mknmz_args = "" if $opt_verbose;
$mknmz_args = $mknmz_args . " " . mknmz_options();

my $tempdir;
my $tempfile;
$tempdir = $ENV{TMPDIR} || $ENV{TEMP} || $ENV{TMP} || '/tmp';
$tempdir =~ s:\\:/:g;
$tempdir =~ s/\/+$//;
$tempdir = sprintf("%s/immknmz-%d-%d", $tempdir, $$, time());
rmdir $tempdir;
unless (mkdir($tempdir, 0700)) {
    print STDERR "$Prog: cannot create directory: $tempdir.\n";
    $tempdir = "";
    exit($EXIT_ERROR);
}
$tempfile = "$tempdir/tempfile";
END {
    if ($tempfile && -f $tempfile) {
	unlink $tempfile;
    }
    if ($tempdir && -d $tempdir) {
	rmdir $tempdir;
    }
}

my $use_dosish_path = ((&win95p() || &os2p()) && !&namazuv2());

sub get_mtime($) {
    my($path) = @_;
    my($dev, $ino, $mode, $nlink, $uid, $gid,
       $rdev, $size, $atime, $mtime, $ctime,
       $blksize, $blocks) = stat($path) or return -1;
    return $mtime;
}

sub make_folder_index($) {
    my($msgfld) = @_;
    my($msgfolder, $msgdir, $nmzfolder, $gcnmztgt, $ret, $timestamp, @filelist);

    $msgfolder = $msgfld;
    $msgfolder =~ s/^\+/$mailpath/g;
    $msgdir = $msgfolder;
    if ($use_dosish_path) {
	$msgfolder =~ s:/:\\:g;
    }

    $nmzfolder = $msgfld;
    $nmzfolder =~ s/^\+/$namazupath/g;

    $timestamp = "$nmzfolder/NMZ.stamp";
    if ($opt_timestamp) {
	my $foldermtime;
	if (&usetouchfile() && -r $msgdir . "/" . &touchfile()) {
	    $foldermtime = get_mtime($msgdir . "/" . &touchfile());
	} else {
	    $foldermtime = get_mtime("$msgdir");
	}
	if (-r $timestamp && $foldermtime < get_mtime("$timestamp")) {
	    print "index of $msgdir may be up to date.\n" if $opt_verbose;
	    flush('STDOUT');
	    return;
	}
    }
    create_folder($nmzfolder);
    if (im_open(\*STAMP, ">$timestamp.new")) {
	print STAMP "touched by IM.";
	close(STAMP);
    }

    opendir(DIR, $msgdir);
    @filelist = grep(/^[0-9]*$/ && -f "$msgdir/$_", readdir(DIR));
    closedir(DIR);

    if (scalar(@filelist) > 0) {
	unless (sysopen(\*TEMPFILE, "$tempfile",
			O_RDWR()|O_CREAT()|O_EXCL(), 0600)) {
	    print STDERR "$Prog: cannot create file: $tempfile.\n";
	    exit($EXIT_ERROR);
	}
	binmode(\*TEMPFILE);
	foreach (@filelist) {
	    if (! -d "$msgdir/$_") {
		if ($use_dosish_path) {
		    print TEMPFILE "$msgfolder\\$_\n";
		} else {
		    print TEMPFILE "$msgfolder/$_\n";
		}
	    }
	}
	close(TEMPFILE);

	print "$Prog: processing $msgfolder...\n";
	flush('STDOUT');
	if ($mknmz_incfile eq "") {
	    $ret = system "mknmz -Uh $mknmz_args -O $nmzfolder -F $tempfile";
	} else {
	    $ret = system "mknmz -Uh $mknmz_args -O $nmzfolder -F $tempfile -I $mknmz_incfile";
	}
	unlink $tempfile;
	if ($ret == 2) {
	    print "$Prog: abort.\n";
	    flush('STDOUT');
	    last;
	} elsif ($opt_gcnmz) {
	    $gcnmztgt = "$nmzfolder" . "/NMZ";
	    print "$Prog: gcnmz $msgfolder...\n" if $opt_verbose;
	    flush('STDOUT');
	    if (&namazuv2()) {
		system "gcnmz --no-backup --quiet $gcnmztgt";
	    } else {
		system "gcnmz $gcnmztgt";
		opendir(DIR, $nmzfolder);
		@filelist = grep(/^.*.BAK$/ && -f "$nmzfolder/$_",
				 readdir(DIR));
		closedir(DIR);
		if (scalar(@filelist) > 0) {
		    foreach (@filelist) {
			unlink "$nmzfolder" . "/$_";
		    }
		}
	    }
	}
    }
    if (-f "$timestamp.new") {
	rename("$timestamp.new", "$timestamp");
    }
}

my %IGNORED_FOLDERS_HASH = ();

sub is_ignored_folder($) {
    my($fld) = @_;
    if ($fld !~ /^\+/) {
	return 1;
    }
    unless (defined($IGNORED_FOLDERS_HASH{'init'})) {
	$IGNORED_FOLDERS_HASH{'fld'} = mknmz_ignore_folders_regex();
	$IGNORED_FOLDERS_HASH{'init'} = 1;
    }
    if ($IGNORED_FOLDERS_HASH{'fld'} eq "") {
	return 0;
    }
    if ($fld =~ /$IGNORED_FOLDERS_HASH{'fld'}/o) {
	return 1;
    }
    return 0;
}

if (@opt_src) {  # folders specified by the --src option
    my $fld;
    foreach $fld (@opt_src) {
	if ($fld !~ /^\+/) {
	    print "skipping $fld...\n" if $opt_verbose;
	    flush('STDOUT');
	} else {
	    make_folder_index($fld);
	}
    }
} else {  # all folders
    my $flds_file = mail_folders_file();
    my $fld;

    im_open(\*FILE, "<$flds_file");
    while (<FILE>) {
	s/\r$// if &win95p() || &os2p();
	chomp;
	$fld = $_;
	if (is_ignored_folder($fld)) {
	    print "skipping $fld...\n" if $opt_verbose;
	    flush('STDOUT');
	} else {
	    make_folder_index($fld);
	}
    }
    close(FILE);
}
exit($EXIT_SUCCESS);

__END__

=head1 NAME

immknmz - make namazu index for mail folders

=head1 SYNOPSIS

B<immknmz> [OPTIONS] [FOLDERS]

=head1 DESCRIPTION

The I<immknmz> command makes namazu index for mail folders.

Folders contained by the ~/Mail/.folders file are used by default.
If you want to specify the folders, use the `--src' option.

This command is provided by IM (Internet Message).

=head1 OPTIONS

=over 5

=item I<-s, --src=FOLDER,FOLDER...>

Set source folders.
"--src=+xxx" is equivalent to "+xxx".

=item I<-g, --gcnmz={on,off}>

Use gcnmz after mknmz (Garbage Collection for Namazu index).

=item I<-v, --verbose={on,off}>

Print verbose messages when running.

=item I<-t, --timestamp={on,off}>

Use checking time stamp.

=item I<-h, --help>

Display help message and exit.

=item I<--version>

Output version information and exit.

=back

=head1 COPYRIGHT

IM (Internet Message) is copyrighted by IM developing team.
You can redistribute it and/or modify it under the modified BSD
license.  See the copyright file for more details.

=cut

### Copyright (C) 1997, 1998, 1999 IM developing team
### All rights reserved.
### 
### Redistribution and use in source and binary forms, with or without
### modification, are permitted provided that the following conditions
### are met:
### 
### 1. Redistributions of source code must retain the above copyright
###    notice, this list of conditions and the following disclaimer.
### 2. Redistributions in binary form must reproduce the above copyright
###    notice, this list of conditions and the following disclaimer in the
###    documentation and/or other materials provided with the distribution.
### 3. Neither the name of the team nor the names of its contributors
###    may be used to endorse or promote products derived from this software
###    without specific prior written permission.
### 
### THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
### ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
### IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
### PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
### LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
### CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
### SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
### BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
### WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
### OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
### IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

### Local Variables:
### mode: perl
### End:
