]> diplodocus.org Git - minc/blobdiff - minc
reindent store_message
[minc] / minc
diff --git a/minc b/minc
index 75fa67e833075bf7c1403c791a6dd29767522332..22ef14397ff52ca7e7177c47405e7ad9d0662b48 100755 (executable)
--- a/minc
+++ b/minc
@@ -108,7 +108,6 @@ GetOptions(
            'r' => \$rebuild_dot_folders,
           ) or pod2usage();
 $help and pod2usage(-exitstatus=>0, -verbose=>1);
-@ARGV <= 1 or pod2usage();
 }
 
 our $run = !$norun;
@@ -142,9 +141,6 @@ $COLUMNS ||= 80;
 if (not $HOME) {
     die("HOME environment variable must be set.\n");
 }
-if (not $MAILDIR) {
-    $MAILDIR = "$HOME/Maildir";
-}
 
 =head1 FILES
 
@@ -334,8 +330,8 @@ sub mark {
     my @sequences = <$fh>;
     chomp(@sequences);
 
-    truncate($fh, 0) or die("truncate($fn): $!");
     seek($fh, 0, SEEK_SET) or die("seek($fn): $!");
+    truncate($fh, 0) or die("truncate($fn): $!");
 
     my $marked = 0;
     for $_ (@sequences) {
@@ -423,77 +419,90 @@ sub lkopen_fcntl {
     die("failed to lock $fn: $!");
 }
 
+my @filtered;
 sub store_message {
-    my $msg = shift;
+    my $inbox = shift;
+    my $msg = shift;            # rename $src_msg
     my $mhfolder = shift;
-    my $msgnum;
-    my $try;
-    my $mhmsg;
+    my ($msgnum, $mhmsg);       # rename $dst_msg and $dst_msgpath
 
     # We must do this even in -n mode because later steps fail without
     # it.  This should be harmless.
     mkfolder($mhfolder);
 
-    # This loop is a modified version of the maildir delivery algorithm.
-    $msgnum = get_highest_msgnum($mhfolder);
-    for ($try = 0; ; $try++) {
-        $msgnum++;
+    if ("+$mhfolder" eq $inbox) {
+        # If @filtered is empty, this message already has the right number.
+        if (!($msgnum = shift(@filtered))) {
+            $msg =~ m|.*/(\d+)$|;
+            return $1;
+        }
         $mhmsg = "$mh/$mhfolder/$msgnum";
-
-        if (not stat($mhmsg)) {
-            if ($!{ENOENT}) {
-                # Now we have a non-existent file, let's try to create
-                # it.  We must create a zero-byte file first because a
-                # file my appear between our happy stat results and
-                # our later rename(2), which would clobber said file.
-                # So attempt to create a file with this name.  If it
-                # succeeds, in just a bit here we'll knowingly clobber
-                # this file with the rename(2) call.
-
-                # Another way to do this is not to use rename(2), but
-                # use link(2) + unlink(2) instead.  That's how the
-                # standard maildir algorithm does it.  Each method has
-                # a disadvantage: the program may crash between the
-                # link(2) and unlink(2) calls.  With the standard
-                # maildir algorithm, that means the message will end
-                # up duplicated.  The advantage of creating an empty
-                # file followed by rename(2) is that an extra empty
-                # file is left behind as opposed to a duplicate
-                # message.  This is more easily detected by the user.
-                if ($run) {
-                    if (sysopen(MSG, $mhmsg,
-                                O_WRONLY | O_EXCL | O_CREAT, 0600)) {
-                        close(MSG);
+    } else {
+        # This loop is a modified version of the maildir delivery algorithm.
+        $msgnum = get_highest_msgnum($mhfolder);
+        my $try;
+        for ($try = 0; ; $try++) {
+            $msgnum++;
+            $mhmsg = "$mh/$mhfolder/$msgnum";
+
+            if (not stat($mhmsg)) {
+                if ($!{ENOENT}) {
+                    # Now we have a non-existent file, let's try to create
+                    # it.  We must create a zero-byte file first because a
+                    # file my appear between our happy stat results and
+                    # our later rename(2), which would clobber said file.
+                    # So attempt to create a file with this name.  If it
+                    # succeeds, in just a bit here we'll knowingly clobber
+                    # this file with the rename(2) call.
+
+                    # Another way to do this is not to use rename(2), but
+                    # use link(2) + unlink(2) instead.  That's how the
+                    # standard maildir algorithm does it.  Each method has
+                    # a disadvantage: the program may crash between the
+                    # link(2) and unlink(2) calls.  With the standard
+                    # maildir algorithm, that means the message will end
+                    # up duplicated.  The advantage of creating an empty
+                    # file followed by rename(2) is that an extra empty
+                    # file is left behind as opposed to a duplicate
+                    # message.  This is more easily detected by the user.
+                    if ($run) {
+                        if (sysopen(MSG, $mhmsg,
+                                    O_WRONLY | O_EXCL | O_CREAT, 0600)) {
+                            close(MSG);
+                            last;
+                        }
+                    } else {
                         last;
                     }
-                } else {
-                    last;
                 }
             }
-        }
 
-        # This algorithm is different from the maildir one; let's make
-        # 10 tries instead of 3.
-        if ($try == 9) {
-            die("Attempted filename $mhmsg exists.");
+            # This algorithm is different from the maildir one; let's make
+            # 10 tries instead of 3.
+            if ($try == 9) {
+                die("Attempted filename $mhmsg exists.");
+            }
+
+            # This algorithm is different; i don't think we need to sleep.
+            #sleep(2);
         }
 
-        # This algorithm is different; i don't think we need to sleep.
-        #sleep(2);
+        if ($run) {
+            # Mark each message as soon as we store it and bomb if that
+            # fails.  While it is slow, it is not safe to store multiple
+            # messages and then have a failure before marking some (or
+            # all).
+            if ($mhfolder ne 'SPAM') {
+                mark($mhfolder, $msgnum, 'unseen');
+            }
+        }
     }
+    push(@filtered, $msg);
 
     if ($run) {
         if (not rename($msg, $mhmsg)) {
             die("rename($msg, $mhmsg): $!");
         }
-
-        # Mark each message as soon as we store it and bomb if that
-        # fails.  While it is slow, it is not safe to store multiple
-        # messages and then have a failure before marking some (or
-        # all).
-        if ($mhfolder ne 'SPAM') {
-            mark($mhfolder, $msgnum, 'unseen');
-        }
     }
 
     return $msgnum;
@@ -635,6 +644,7 @@ sub scan_line {
 }
 
 sub filter_mail {
+    my $inbox = shift;
     @_ or return ();
     my $msgcount = @_ - 2; # don't count . and ..
     my $len = length($msgcount);
@@ -646,10 +656,6 @@ sub filter_mail {
     my $msgnum;
     my %folders;
 
-    if (-f "$HOME/.minc") {
-        require "$HOME/.minc";
-    }
-
     # XXX lame names
     my $nf = int($COLUMNS * $SCAN_P_FOLDER);
     my $nm = int($COLUMNS * $SCAN_P_MESSAGE);
@@ -683,7 +689,7 @@ sub filter_mail {
 
         defined($mhfolder) or ($mhfolder = find_mh_folder($msg, $headers));
 
-        $msgnum = store_message($msg, $mhfolder);
+        $msgnum = store_message($inbox, $msg, $mhfolder);
         $folders{$mhfolder}++;
 
         if ($tty) {
@@ -861,37 +867,45 @@ if (!caller()) {
 
     $rebuild_dot_folders and exit(create_dot_folders);
 
-    my @files;
-    # XXX some options:
-    # a. take message numbers on stdin
-    # b. take full paths to messages on stdin
-    # c. take standard [msgs] list on command-line
-    # d. assume inc has just finished so cur points to start of new mail and
-    #    just do cur-last
-    # Hacked up b. here, but I'm not happy with it.  I'm renaming files that
-    # stay in inbox for no reason, and leaving gaping holes.  Any of the above
-    # approaches has those problems, and the solution is always the same:
-    # # Keep track of the message numbers we've renamed out of inbox
-    # my @filtered;
-    # for (@msgs) {
-    #     if (!my $new = filter($_)) {
-    #         # If @filtered is empty, this message already has the right number.
-    #         $new = shift(@filtered) || next;
-    #     }
-    #     push(@filtered, $_);
-    #     rename($_, $new);
-    # }
+    if (-f "$HOME/.minc") {
+        require "$HOME/.minc";
+    }
+
+    my $inbox;
+    if ($MAILDIR) {
+        $inbox = $MAILDIR;
+    } elsif (-d "$HOME/Maildir") {
+        $inbox = "$HOME/Maildir";
+    }
 
     if (@ARGV > 0) {
-        # XXX if sticking with this approach, reject arg other than '-'
-        chomp(@files = <>);
-        @files > 0 || exit 0;
-    } else {
-        chdir("$MAILDIR/new") or die("chdir($MAILDIR/new): $!");
-        @files = getfiles('.');
+        $inbox = shift(@ARGV);
     }
 
-    my %folders = filter_mail(map { $_->[1] }
+    my @files;
+    if (substr($inbox, 0, 1) eq '+') {
+        my @msgs = @ARGV;
+        if (!@msgs) {
+            @msgs = ('cur-last');
+        }
+        open(my $fh, '-|', 'mhpath', @msgs) or die("open(mhpath|): $!");
+        chomp(@files = <$fh>);
+        if (!close($fh)) {
+            $! == 0 or die("open(mhpath|): $!");
+            die('mhpath '. exit_msg($?));
+        }
+        @files > 0 or exit 0;
+    } else {
+        @ARGV == 0 or pod2usage();
+        chdir("$inbox/new") or die("chdir($inbox/new): $!");
+        @files = map { $_->[1] }
+          sort { $a->[0] <=> $b->[0] }
+          map {
+              $st = stat($_) or die("stat($_): $!");
+              [ $st->mtime, $_ ]
+          } getfiles('.');
+
+        @files = map { $_->[1] }
                 sort { $a->[0] <=> $b->[0] }
                 map {
                     if (not ($st = stat($_))) {
@@ -899,7 +913,10 @@ if (!caller()) {
                     }
                     [$st->mtime, $_]
                 }
-                @files);
+                getfiles('.');
+    }
+
+    my %folders = filter_mail($inbox, @files);
 
     $run and %folders and update_dot_folders(\%folders);