5 m2n - a mail2news(1) replacement
13 A replacement for I<mail2news> from the newsgate package. Uses I<rnews> instead
14 of I<inews> by default, and is much less insistent on removing useful headers.
18 Long option names may be abbreviated to uniqueness.
24 Send output to standard output rather than directly to I<rnews>.
26 =item B<-a>, B<--approved>=I<approved>
28 Approved: line, if none is specified.
30 =item B<-d>, B<--distribution>=I<distribution>
32 Distribution: line, if none is specified.
34 =item B<-n>, B<--newsgroups>=I<newsgroups>
36 Newsgroups: line, overriding any such provided. Newsgroups: lines in the input
37 will be saved in X-Mail2News-Newsgroups: lines.
39 =item B<-o>, B<--organization>=I<organization>
41 Organization: line, if none is specified.
43 =item B<-s>, B<--subject>=I<subject>
45 Subject: line, if none is specified; the default is "no subject".
47 =item B<-x>, B<--path>=I<path>
49 Path: prefix, if none is specified; the default is "gateway".
53 =head1 ERROR REPORTING
55 Errors will be logged using syslog(3).
63 I<m2n> and this manual page were written by Colin Watson <cjw44@cam.ac.uk>.
70 use Digest::MD5 qw(md5_base64);
72 use Sys::Syslog qw(:DEFAULT setlogsock);
74 $ENV{PATH} = '/usr/bin:/bin';
76 # Use syslog(3) for error output.
79 openlog 'mail2news', 'pid', 'news';
91 my ($approved, $distribution, $newsgroups, $organization);
92 my $subject = 'no subject';
95 Getopt::Long::Configure qw(bundling bundling_override);
97 "stdout" => \$tostdout,
98 "approved|a=s" => \$approved,
99 "distribution|d=s" => \$distribution,
100 "newsgroups|n=s" => \$newsgroups,
101 "organization|o=s" => \$organization,
102 "subject|s=s" => \$subject,
103 "path|x=s" => \$path);
107 my $headerblock = '';
110 my ($hname, $hvalue);
117 syslogdie 'No headers found, aborting' unless defined $hname;
118 $headers{lc $hname} = $hvalue;
128 syslogdie "Continuation line at start of headers: '$line'"
129 unless defined $hvalue;
132 elsif (/^(.*?):[ \t](.*)/)
134 $headers{lc $hname} = $hvalue if defined $hname;
138 if ($hname =~ /newsgroups/i && defined $newsgroups)
140 $hname = 'X-Mail2News-Newsgroups';
141 $headerblock .= "Newsgroups: $newsgroups\n";
142 $headers{newsgroups} = $newsgroups;
145 elsif ($hname =~ /path/i && defined $path)
147 $hvalue = "$path!$hvalue";
149 $_ = "$hname: $hvalue\n";
153 $headers{lc $hname} = $hvalue if defined $hname;
157 if ($hname =~ /newsgroups/i && defined $newsgroups)
159 $hname = 'X-Mail2News-Newsgroups';
160 $headerblock .= "Newsgroups: $newsgroups\n";
161 $headers{newsgroups} = $newsgroups;
164 elsif ($hname =~ /path/i && defined $path)
168 $_ = "$hname: $hvalue\n";
173 syslogdie "Invalid header line: '$line'";
176 if ($overridden) { $extra .= $_; }
177 else { $headerblock .= $_; }
183 # Headers from command line
185 $extra .= "Approved: $approved\n"
186 if defined $approved and not defined $headers{approved};
187 $extra .= "Distribution: $distribution\n"
188 if defined $distribution and not defined $headers{distribution};
189 $extra .= "Newsgroups: $newsgroups\n"
190 if defined $newsgroups and not defined $headers{newsgroups};
191 $extra .= "Organization: $organization\n"
192 if defined $organization and not defined $headers{organization};
193 $extra .= "Subject: $subject\n"
194 if defined $subject and not defined $headers{subject};
195 $headerblock = "Path: $path\n$headerblock"
196 if defined $path and not defined $headers{path};
198 # Other required header checks
200 syslogdie 'No From: line, aborting' unless defined $headers{from};
201 $extra .= time2str 'Date: %a, %e %h %Y %T GMT' . "\n", time, 'GMT'
202 unless defined $headers{date};
203 $extra .= sprintf "Message-ID: <mail2news.\%x.\%s\@riva.ucam.org>\n",
204 time, md5_base64($body) unless defined $headers{'message-id'};
206 # Output to stdout or rnews.
210 print $headerblock, $extra, "\n", $body;
214 $SIG{PIPE} = 'IGNORE';
215 open RNEWS, '| rnews -v 2>/dev/null' or syslogdie "can't fork: \%m";
216 print RNEWS $headerblock, $extra, "\n", $body
217 or syslogdie "can't write: \%m";
218 close RNEWS or syslogdie "can't close: \%m";