3
eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
4
if 0; # not running under some shell
6
# to create a manpage for mailman2lurker, invoke the following command:
7
# pod2man --section=8 --center="Administrative commands" --release="" mailman2lurker mailman2lurker.8
11
mailman2lurker - Import mailman lists and their archives into a lurker database.
15
Z<> B<mailman2lurker> B<-i>|B<-p> [I<options>]
19
B<mailman2lurker> has mainly two functions. First, it parses mailman's lists
20
and creates a lurker configuration include out of them. Second, it imports
21
archives from mailman lists into a lurker database.
23
To build a new lurker database from mailmans archives, first run
24
'B<mailman2lurker -p>'. Next you need to add 'B<include =
25
/etc/lurker/lurker.conf.mailman>' into /etc/lurker/lurker.conf.local.
26
Finally import mailmans mboxes by running 'B<mailman2lurker -i>'.
28
If you want to add new lists to an already existing lurker configuration, run
29
'B<mailman2lurker -p -w newlists>' and afterwards 'B<mailman2lurker -i -f
30
newlists>'. This will import only the mbox files of mailman lists that have been
31
added to the lurker configuration because they were new to lurker.
37
=item B<-p>, B<--parse>
39
Parse mailman lists, and create a lurker configuration include file containing
40
all parsed lists. Lists that are already configured in lurker are ignored.
42
=item B<-i>, B<--import>
44
Import archives of all lists. This parses the lurker configuration and imports
45
the mailman mbox at /var/lib/mailman/archives/private/<list>.mbox/<list>.mbox
52
=item B<-c>, B<--config> <I<config>>
54
Use <I<config>> as lurker configuration file. Default: /etc/lurker/lurker.conf
56
=item B<-o>, B<--outfile> <I<outfile>>
58
Write list configuration to <I<outfile>>. If this is not specified,
59
<lurker.conf>.mailman will be used.
60
This option is only useful in conjunction with B<-p>.
62
=item B<-g>, B<--group> <I<group>>
64
Use <I<group>> for new lists. Default is 'undef'.
65
This option is only useful in conjunction with B<-p>.
67
=item B<-a>, B<--listhost> <I<listhost>>
69
Use <I<listhost>> as host for new list addresses. If a new list is called
70
'mylist' and <I<listhost>> is lists.org, then the list address will be
71
mylist@lists.org. Default is 'example.org'.
72
This option is only useful in conjunction with B<-p>.
74
=item B<-l>, B<--link> <I<url link>>
76
Use <I<url link>> as base for links of new lists. If a list is called 'mylist',
77
and <I<url link>> is 'http://lists.org', then the link address will be
78
http://lists.org/mylist. Default is 'http://example.org'.
79
This option is only useful in conjunction with B<-p>.
81
=item B<-s>, B<--lang> <I<language>>
83
Use <I<language>> as language for new lists. Needs to be a language token.
84
Default is 'en'. This option is only useful in conjunction with B<-p>.
86
=item B<-w>, B<--write-lists> <I<file>>
88
Write a list of all lists that have been added to the lurker configuration.
89
Safe that list in <I<file>>. Default is off.
90
This option is only useful in conjunction with B<-p>.
92
=item B<-x>, B<--list-cmd> <I<file>>
94
Use <I<command|file>> to get the list of mailman lists that should be parsed.
95
When <I<command|file>> is a command, it needs to end with ' |'.
96
Default is '/var/lib/mailman/bin/list_lists |'.
97
This option is only useful in conjunction with B<-p>.
99
=item B<-f>, B<--listfile> <I<file>>
101
Import only lists that are listed in <I<file>>.
102
This option is only useful in conjunction with B<-i>.
104
=item B<-d>, B<--lists> <I<one>[,I<two>,I<...>]>
106
Import only lists that are given as argument.
107
This option is only useful in conjunction with B<-i>.
109
=item B<-h>, B<--help>
111
Display a help message.
113
=item B<-v>, B<--version>
115
Display mailman2lurker's version number.
119
L<list_lists(8)>, L<lurker-index(8)>
123
This program was written by Jonas Meurer <jonas@freesources.org>.
127
mailman2lurker may be copied and modified under the terms of the GNU General
136
use File::Temp qw/ tempfile /;
138
# Display mailman2lurker's version number.
140
print "mailman2lurker version $Version\n";
144
# Display usage help.
147
mailman2lurker - Import mailman lists and their archives into a lurker database
149
Usage: mailman2lurker -p|-i [options]
152
-c, --config <config> use this conffile (default: /etc/lurker/lurker.conf)
153
-i, --import import list archives from mailman's mbox files
154
-f, --listfile <file> import only lists in <file>.
155
-d, --lists <one,two,..> import only lists that are given as argument.
156
-p, --parse create a lurker conf include from mailman lists
157
-o, --outfile <outfile> write to this file. (default: <config>.mailman)
158
-g, --group <group> use this group for lists. (default: undef)
159
-a, --listhost <host> use this host for lists. (default: example.org)
160
-l, --link <url link> use for the url link. (default: listurl)
161
-s, --lang <language> use this language for new lists. (default: en)
162
-w, --write-lists <file> write a list of parsed lists to <file>.
163
-x, --list-cmd <cmd|file> use this command/file as list of mailman lists.
164
(default: "/usr/lib/mailman/bin/list_lists |")
165
-h, --help Display this help message.
166
-v, --version Display mailman2lurker's version number.
174
my $lurkergroups = "/usr/bin/lurker-list -g |";
175
open LURKERGROUPS, $lurkergroups or die "Could not open $lurkergroups: $!";
176
while (<LURKERGROUPS>) {
178
print STDERR "Group $group already exists in lurker configuration, you need to configure another one with -g.\n";
187
my $lurkerlist = "/usr/bin/lurker-list -c $glob::lurkerconf -i |";
188
open LURKERLIST, $lurkerlist or die "Could not open $lurkerlist: $!";
189
while (<LURKERLIST>) {
191
if (($list) = /^([0-9-_\w]*)$/) {
200
my ($list_cmd, $defgroup, $listhost, $listurl, $lang) = @_;
201
my ($list, $desc, %mmlists);
202
my ($fh, $filename) = tempfile();
203
open my $ll_exec, $list_cmd or die "Could not open $list_cmd: $!";
204
while (<$ll_exec>) { print $fh $_; };
208
my $ll_charset = uc(`/usr/bin/file -i $filename | sed -e 's/^.*charset=//g'`);
211
my @list_lists = `/usr/bin/iconv -f $ll_charset -t UTF-8 $filename`;
216
next unless (($list, $desc) = /^\s*([0-9-_\w]*)\s-\s(.*)\s*$/);
217
if ($desc eq "[no description available]") {
220
my $list_lc = lc($list);
221
if (not (grep(/$list_lc/, @glob::lurkerlists))) {
222
$mmlists{$list_lc} = { id => $list_lc,
225
address => $list . '@' . $listhost,
226
link => $listurl . '/' . $list,
231
my $mmlref = \%mmlists;
237
my %dlists = %$dlref;
238
my ($group, $writeflag) = "";
239
open LOCALCONF, ">> $glob::localconf" or die "Could not open $glob::localconf: $!";
240
if ($glob::writefile ne "") {
242
open WRITEFILE, "> $glob::writefile" or die "Could not open $glob::writefile: $!";
244
#for $_ (sort { $dlists{$a}{id} cmp $dlists{$b}{id} } keys %dlists) {
245
for $_ (sort {($dlists{$a}{group} cmp $dlists{$b}{group} ) or ($dlists{$a}{id} cmp $dlists{$b}{id} ) } keys %dlists) {
246
unless ($dlists{$_}{group} eq $group)
248
$group = $dlists{$_}{group};
249
print LOCALCONF "\n";
250
print LOCALCONF "group = $group\n";
251
print LOCALCONF " heading = $group\n";
252
print LOCALCONF "\n";
254
print LOCALCONF " list = $dlists{$_}{id}\n";
255
print LOCALCONF " title = $dlists{$_}{title}\n";
256
print LOCALCONF " language = $dlists{$_}{lang}\n";
257
print LOCALCONF " address = $dlists{$_}{address}\n";
258
print LOCALCONF " link = $dlists{$_}{link}\n";
259
print LOCALCONF " description = $dlists{$_}{desc}\n";
260
print LOCALCONF "\n";
261
if ($writeflag) { print WRITEFILE "$dlists{$_}{id}\n"; }
263
if ($writeflag) { close WRITEFILE; }
269
my @ulists = @$iulref;
270
my $ulfile = pop(@ulists);
272
if ($ulfile ne " ") {
274
open ULFILE, $ulfile or die "Could not open $ulfile: $!";
282
print STDERR "file $ulfile does not exist.\n";
290
@lists = @glob::lurkerlists;
292
for my $list (@lists) {
293
my $mbox = "/var/lib/mailman/archives/private/$list.mbox/$list.mbox";
295
if(system("/usr/bin/lurker-index", "-c", "$glob::lurkerconf", "-l", "$list", "-i", "$mbox") != 0) {
296
print STDERR "archives for $list could not be imported.\n";
300
print STDERR "no archives available for $list at $mbox.\n";
305
my ($listhost, $defgroup, $listurl, $language, $ll_cmd) =
306
("example.org", "undef", "http://example.org", "en",
307
"/usr/lib/mailman/bin/list_lists |");
308
my ($import, $parse, $uselistfile, @uselists);
309
$glob::lurkerconf = "/etc/lurker/lurker.conf";
310
$glob::localconf = "$glob::lurkerconf.mailman";
311
$glob::writefile = "";
312
@glob::lurkerlists = ();
313
my @list_props = qw/title address link language description/;
315
# Bundling is nice anyway, and it is required or Getopt::Long will confuse
317
Getopt::Long::Configure("bundling");
320
'a|listhost=s' => \$listhost,
321
'i|import' => sub { $import=1 },
322
'f|listfile=s' => \$uselistfile,
323
'd|lists=s' => \@uselists,
324
'c|config=s' => \$glob::lurkerconf,
325
'g|group=s' => \$defgroup,
327
'l|link=s' => \$listurl,
328
'o|outfile=s' => \$glob::localconf,
329
'p|parse' => sub { $parse=1 },
330
's|language=s' => \$language,
331
'v|version' => \&version,
332
'w|write-lists=s' => \$glob::writefile,
333
'x|list-cmd=s' => \$ll_cmd );
334
@uselists = split(/,/,join(',',@uselists));
336
@glob::lurkerlists = lurker_lists();
338
if ($parse && $import) {
339
print STDERR "--parse and --import cannot be used together.\n";
343
check_group($defgroup);
344
my $mmmlref = mailman_lists($ll_cmd, $defgroup, $listhost, $listurl, $language);
345
dump_lists($mmmlref);
347
elsif ($import && $uselistfile && @uselists) {
348
print STDERR "--listfile and --lists cannot be used together.\n";
352
if (not ($uselistfile)) { $uselistfile = " "; }
353
push @uselists, $uselistfile;
354
my $ulref = \@uselists;
355
import_lists($ulref);