[Mew-dist 14538] Re: incdir, incmbox
Shun-ichi TAHARA ( 田原 俊一 )
jado at example.com
2000年 10月 14日 (土) 01:09:40 JST
From: Yasunari Momoi <momo at example.com>
Message-Id: <20001012.230146.97297082.momo at example.com>
> Maildir から mail を取り込む incdir と,mbox から mail を取
> り込む incmbox です.incdir は sh script,incmbox は perl で
> 書いてあります.
う、先を越された :-)。
こちらでは、movemailを使わない mewinc を作ってみました。
# というか、imget から local mbox 関連の部分を抜き出したものですが。
せっかくですので流しておきます。
% mewinc [-obeycl] [-uselockfile] [-mailbox file] [+folder]
として起動すると、メールボックスからカレントディレクトリに落としてきま
す。ただ、誤って変なところにメールを飛ばすのを防ぐために、cwd() と
".*/folder$" とのマッチングを行ないます(デフォルトは inbox)。
-obeycl を指定すると、Content-Length: へッダを見ます。
また、-uselockfile を指定すると、flock() の代わりにロックファイルを作
ります。
メールボックスは自動的に guess しますが、-mailbox オプションで指定する
こともできます。
対応 mbox 形式はよくわかっていませんが :-)、imget が扱える形式はオッケー
のはずです。って、ちらっと見た感じでは特にunquoteはしないように見えま
すが。
注意点としては、UNIX以外のOSに対応するコードは全部削ってしまっているこ
とと、NFSな人は、$fsync_no にシステムコール番号を代入しておくことです。
わからない方は、下記のコードをコンパイルして実行すれば調べられます。
--------
#include <stdio.h>
#include <sys/syscall.h>
int main() {
printf("%d\n", SYS_fsync);
return 0;
}
--------
# configureでどうにかした方がいいのかなあ…
_______________________________
田原 俊一 jado at example.com, shunichi_tahara at example.com
http://flowernet.gr.jp/jado/
FingerPrint: 16 9E 70 3B 05 86 5D 08 B8 4C 47 3A E7 E9 8E D9
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
-------------- next part --------------
#!/usr/local/bin/perl
#
# mewinc: mewls helper for local spool
# [from imget]
#
# Author: Shun-ichi TAHARA <jado at example.com>
# Time-stamp: <00/10/14 00:50:44 jado at example.com>
#
require 5.003;
use Cwd;
use Fcntl;
use integer;
$obeycl = 0;
$uselockfile = 0;
$folder = '+inbox';
$mbopt = 0;
$mailbox = '';
$fsync_no = undef;
#$fsync_no = "118"; # Linux
sub fsync ($) {
my ($fno) = @_;
if ($fsync_no) {
return syscall($fsync_no, $fno);
}
return 0;
}
sub LOCK_SH { 1 }
sub LOCK_EX { 2 }
sub LOCK_NB { 4 }
sub LOCK_UN { 8 }
sub lockmbox ($) {
my ($base) = @_;
my $retry = 0;
$locked_by_file = 0;
$locked_by_flock = 0;
if ($uselockfile) {
unless (open(LOCKFILE, ">$base.$$")) {
return -1;
}
binmode(LOCKFILE);
print LOCKFILE "$$\n";
close(LOCKFILE);
while (!link("$base.$$", "$base.lock")) {
if ($retry >= 10) {
unlink("$base.$$");
return -1;
}
$retry++;
sleep(5);
}
unlink("$base.$$");
$locked_by_file = 1;
} else {
unless (open(LOCK_FH, "+<$base")) {
return -1;
}
unless (flock (LOCK_FH, LOCK_EX|LOCK_NB)) {
return -1;
}
$locked_by_flock = 1;
}
return 0;
}
sub unlockmbox ($) {
my ($base) = @_;
if ($locked_by_file) {
$locked_by_file = 0;
if (-f "$base.lock" && unlink("$base.lock") <= 0) {
return -1;
}
}
if ($locked_by_flock) {
$locked_by_flock = 0;
flock(LOCK_FH, LOCK_UN);
}
return 0;
}
sub empty_mbox ($) {
my ($mbox) = @_;
unless (truncate($mbox, 0)) {
unless (open(MBOX, ">$mbox")) {
print STDERR "Can't clear mailbox.\n";
return;
}
close(MBOX);
}
}
sub message_number {
my ($number, @files);
opendir(DIR, '.') or die "Can't open current directory, stopped";
@files = sort {$a <=> $b} grep /^\d+$/, readdir(DIR);
closedir(DIR);
if (scalar(@files) == 0) {
$number = '1';
} else {
$number = $files[$#files] + 1;
}
while (-e "$number" || -e ".$number.dir") {
$number++;
}
return $number;
}
sub excl_create (*$) {
(local *MESSAGE, my $file) = @_;
my ($attr);
$attr = Fcntl::O_RDWR() | Fcntl::O_CREAT() | Fcntl::O_EXCL();
umask(066);
sysopen(MESSAGE, $file, $attr) or return -1;
binmode(MESSAGE);
return 0;
}
$msgnum = 0;
sub new_message (\*) {
local (*MESSAGE) = @_;
my ($try);
if ($msgnum == 0) {
$msgnum = message_number();
} else {
$msgnum++;
}
$try = 3;
while ($try--) {
if (excl_create(\*MESSAGE, "$msgnum") == 0) {
# created successfully
return "$msgnum";
}
$msgnum++;
}
# message creation failed
return '';
}
sub store_message ($) {
my ($Msg) = @_;
local (*ART);
my ($file, $size);
$file = &new_message(\*ART);
$size = 0;
if ($file ne '') {
my ($hcount, $inheader);
$hcount = 0;
$inheader = 1;
select (ART); $| = 1; select (STDOUT);
foreach (@$Msg) {
$size += length($_);
if ($_ eq "\n") {
$inheader = 0;
}
$hcount++ if ($inheader);
unless (print ART $_) {
goto ERR1;
}
}
if (fsync(fileno(ART)) < 0) {
goto ERR1;
}
unless (close(ART)) {
goto ERR2;
}
print "$file\n";
return 0;
ERR1:
close(ART);
ERR2:
print STDERR "Writing to the file \"$file\" failed ($!).\n";
unlink($file) if (-z $file);
return -1;
} else {
im_err("message can not be saved to $dst.\n");
return -1;
}
}
sub process_mbox ($) {
my ($src) = @_;
my ($format, $msgs, $length, $inheader, @Message);
local (*MBOX);
my ($first_line);
unless (open(MBOX, "<$src")) {
return -1;
}
chomp($first_line = <MBOX>);
if ($first_line =~ /^From /) {
$format = 'UNIX';
} elsif ($first_line =~ /^\001\001\001\001$/) {
$format = 'MMDF';
} elsif ($first_line =~ /^BABYL OPTIONS:/) {
$format = 'RMAIL';
} else {
print STDERR "invalid mbox format: $src\n";
return -1;
}
$msgs = 0;
while ($first_line ne '') {
if ($msgs > 0 && $format eq 'MMDF') {
$first_line = <MBOX>;
if ($first_line !~ /^\001\001\001\001$/) {
last;
}
}
if ($format eq 'RMAIL') {
while (<MBOX>) {
last if /^\*\*\* EOOH \*\*\*$/;
}
}
if ($format eq 'UNIX') {
# convert UNIX From_ into Return-Path
my $rp = $first_line;
$rp =~ s/^From +//;
$rp =~ s/ +[A-Z][a-z][a-z] [A-Z][a-z][a-z] [\d ]\d \d\d:\d\d.*//;
$rp = "<$rp>" if ($rp !~ /^<.*>$/);
@Message = ("Return-Path: $rp\n");
} else {
@Message = ();
}
$first_line = '';
$inheader = 1;
$length = -1;
while (<MBOX>) {
if ($format eq 'MMDF' && /^\001\001\001\001$/) {
$first_line = 'MMDF';
last;
} elsif ($format eq 'UNIX' && $length <= 0
&& /^From / && $Message[$#Message] eq "\n") {
chomp($first_line = $_);
last;
} elsif ($format eq 'RMAIL' && /^\x1f/ ) {
chomp($first_line = <MBOX>);
last;
} elsif ($inheader) {
# XXX continuous line processing needed
push (@Message, $_);
# for Solaris 2.x or ...
# XXX option
if ($obeycl && /^Content-Length:(.*)/i) {
chomp($length = $1);
}
$inheader = 0 if (/^\n$/);
} else {
push (@Message, $_);
$length -= length($_) if ($length > 0);
}
}
if ($Message[$#Message] eq "\n") {
pop (@Message);
}
$msgs++ if ($#Message >= 0);
if (store_message(\@Message) < 0) {
close(MBOX);
return -1;
}
}
close(MBOX);
print STDERR "$msgs message(s).\n";
return $msgs;
}
sub getmsg ($) {
my ($src) = @_;
my ($msgs);
# set default
unless ($src) {
my $user = getlogin();
if ($user eq '' || $user eq 'root') {
$user = (getpwuid($<))[0];
}
foreach ("/var/mail/$user", "/var/spool/mail/$user",
"/usr/mail/$user", "/usr/spool/mail/$user"
) {
if (-f $_) {
$src = $_;
last;
}
}
unless ($src) {
die "Mailbox for $user not found, stopped";
}
}
if (-s $src) {
# FILE and not ZERO
if (&lockmbox($src) < 0) {
&unlockmbox($src);
die "Can't lock mailbox \"$src\", stopped";
}
if (($msgs = process_mbox($src)) < 0) {
&unlockmbox($src);
die "Can't get message from mailbox \"$src\", stopped";
}
&empty_mbox($src);
&unlockmbox($src);
return $msgs;
} else {
print STDERR "No messages in mailbox.\n";
return 0;
}
}
sub usage {
print "Usage: mewinc [-obeycl] [-uselockfile] [-mailbox file] [+folder]\n";
exit(0);
}
foreach (@ARGV) {
if ($mbopt) {
$mbopt = 0;
$mailbox = $_;
} elsif (/^-obeycl$/) {
$obeycl = 1;
} elsif (/^-uselockfile$/) {
$uselockfile = 1;
} elsif (/^-mailbox$/) {
$mbopt = 1;
} elsif (/^-h/) {
&usage();
} elsif (/^-/) {
die "Unknown switch \"$_\", stopped";
} else {
$folder = $_;
}
}
if ($mbopt) {
die "Filename expected after \"-mailbox\", stopped";
}
$_ = $folder;
s:^.(.*)$:.*/$1\$:;
if (cwd() !~ /$_/) {
die "Must be executed on the folder \"$folder\", stopped";
}
&getmsg($mailbox);
exit(0);
# mewinc ends here.
-------------- next part --------------
******************************* mewinc *******************************
mbox形式のローカルスプールからメールを取得する際に、mewlsから呼び出さ
れるへルパスクリプトです。
imgetからlocal mbox関連の部分を抜き出したものですので、imgetが扱える形
式は全て扱えるはずです。
使い方 ---------------------------------
(setq mew-mailbox-type 'mbox)
(setq mew-mbox-command "mewinc")
とすればオッケーです。mew-config-alist 内で設定する場合は、
(setq mew-config-alist
'(("default"
:
("mailbox-type" . mbox)
("mbox-command" . "mewinc")
:
)
("foo"
:
)))
などとします。
mewincにオプションを渡す際は、mew-mbox-command-arg を設定してください。
mew-config-alist なら、"mbox-command-arg" で指定します。
オプションについて ---------------------
mewincには、-obeycl, -uselockfile, -mailbox, -help の4つのオプションが
指定可能です。
・-obeycl
Content-Length: へッダを見ます。Solaris等、SYSV系OSで必要な場合があ
ります。
・-uselockfile
flock()を使わず、ロックファイルを用いてメールスプールをロックします。
・-mailbox file
メールスプールファイルを指定します。
・-help
コマンドラインへルプを表示します。
動作について ---------------------------
mewincを
% mewinc [options] [+folder]
として起動すると、メールスプールからカレントディレクトリに落としてきま
す。mewls以外から起動した際に、誤って変なディレクトリにメールを取り込
んでしまうのを防ぐために、cwd()と ".*/folder$" とのマッチングを行ない
ます(デフォルトは inbox)。
メールスプールは、/{usr|var}/[spool]/mail/$user の中から自動的に探され
ますが、見つけきれないときは -mailbox オプションで指定する必要がありま
す。
対応mbox形式はよくわかっていませんが :-)、imgetが扱える形式は大丈夫の
はずです。imgetと同様、特にunquoteはしません。
注意点 ---------------------------------
UNIX以外のOSに対応するコードは全部削ってしまっていますので、おそらくう
まく動かないでしょう。
また、fsync()で同期を取りたい場合は、スクリプト中の $fsync_no にシステ
ムコール番号を代入しておく必要があります。デフォルトでは undef になっ
ており、この場合はfsync()は行なわれません。特にメールフォルダがNFS上に
ある場合は、設定したほうがいいでしょう。
システムコール番号がわからない方は、下記のコードをコンパイルして実行す
れば調べられます。本当はautoconfを使うべきなのかもしれませんが。
------------------------------------
#include <stdio.h>
#include <sys/syscall.h>
int main() {
printf("%d\n", SYS_fsync);
return 0;
}
------------------------------------
_______________________________
田原 俊一 jado at example.com, shunichi_tahara at example.com
http://flowernet.gr.jp/jado/
Fingerprint: 16 9E 70 3B 05 86 5D 08 B8 4C 47 3A E7 E9 8E D9
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
Mew-dist メーリングリストの案内