def deliver(io_or_string, action='new')
tmp_name = nil
new_name = nil
hostname = Socket::gethostname.gsub(/[^\w]/, '_').untaint
pid = Process::pid
3.times do |counter|
now = Time.now
basename = sprintf("%d.M%XP%d_%d.%s",
Time::now.tv_sec, Time::now.tv_usec, pid, @@sequence_number, hostname)
@@sequence_number += 1
tmp_name = @directory + 'tmp' + basename
case action.to_s
when 'new'
new_name = @directory + 'new' + basename
when 'old'
new_name = @directory + 'cur' + ( basename + ':2,' )
when 'seen'
new_name = @directory + 'cur' + ( basename + ':2,S' )
else
raise Error, "unknown action '#{action}'"
end
begin
File::stat(tmp_name)
rescue Errno::ENOENT
break
rescue Exception
raise if i == 2
end
if i == 2
raise "Too many tmp file conflicts."
else
sleep(2)
end
end
begin
File.open(tmp_name, File::CREAT|File::EXCL|File::WRONLY, 0600) do |f|
first = true
io_or_string.each_line do |line|
if first
first = false
next if line =~ /From /
end
f << line
f << "\n" unless line[-1] == ?\n
end
f.fsync if defined? f.fsync
end
File.link(tmp_name, new_name)
ensure
begin
File.delete(tmp_name)
rescue Errno::ENOENT
end
end
end