sympa_wizard.pl.in 23.1 KB
Newer Older
salaun's avatar
 
salaun committed
1
#!--PERL--
2
3
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
4
# $Id$
salaun's avatar
 
salaun committed
5
6

# Sympa - SYsteme de Multi-Postage Automatique
7
8
9
10
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
11
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
12
13
# Copyright 2018, 2021 The Sympa Community. See the
# AUTHORS.md file at the top-level directory of this distribution and at
14
# <https://github.com/sympa-community/sympa.git>.
salaun's avatar
 
salaun committed
15
16
17
18
19
20
21
22
23
24
25
26
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
27
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
salaun's avatar
 
salaun committed
28

29
use lib '--modulesdir--';
30
use strict;
sikeda's avatar
sikeda committed
31
use warnings;
IKEDA Soji's avatar
IKEDA Soji committed
32
use Encode qw();
33
34
35
use English qw(-no_match_vars);
use Getopt::Long;
use Pod::Usage;
sikeda's avatar
sikeda committed
36
use Sys::Hostname qw();
37

38
use Sympa::ConfDef;
39
use Sympa::Constants;
40

41
42
my $with_CPAN;    # check if module "CPAN" installed.
my $modfail;      # any of required modules are not installed.
43
44
45

BEGIN {
    $with_CPAN = eval { require CPAN; };
46
47
48
49
50
    $modfail = !eval {
        require Conf;
        require Sympa::Language;
        require Sympa::Tools::Text;
    };
51
52
}

53
54
55
56
57
# Detect console encoding.
if (-t) {
    no warnings;

    eval { require Encode::Locale; };
58
    unless ($EVAL_ERROR
59
60
61
        or Encode::resolve_alias($Encode::Locale::ENCODING_CONSOLE_IN) eq
        'ascii'
        or Encode::resolve_alias($Encode::Locale::ENCODING_CONSOLE_OUT) eq
62
63
64
65
66
67
68
69
70
71
72
        'ascii') {
        binmode(STDIN,  ':encoding(console_in):bytes');
        binmode(STDOUT, ':encoding(console_out):bytes');
        binmode(STDERR, ':encoding(console_out):bytes');
    }
}

# Set language context if possible.
if ($modfail) {
    no warnings;

73
    *gettext = sub { $_[1] ? sprintf('%*s', $_[1], $_[0]) : $_[0] };
74
75

    eval { require Text::Wrap; };
76
    if ($EVAL_ERROR) {
77
        *Sympa::Tools::Text::wrap_text = sub {"$_[1]$_[0]\n"};
78
79
    } else {
        $Text::Wrap::columns = 78;
80
        *Sympa::Tools::Text::wrap_text =
81
82
83
            sub { Text::Wrap::wrap($_[1], $_[2], $_[0]) . "\n"; };
    }
} else {
84
85
86
    no warnings;

    my $language = Sympa::Language->instance;
87
88
89
90
91
    *gettext = sub {
        $_[1]
            ? Sympa::Tools::Text::pad($language->gettext($_[0]), $_[1])
            : $language->gettext($_[0]);
    };
92

93
94
    my $lang = $ENV{'LANGUAGE'} || $ENV{'LC_ALL'} || $ENV{'LANG'};
    $lang =~ s/\..*// if $lang;
95
    $language->set_lang($lang, 'en-US', 'en');
96
97
}

98
## sympa configuration file
99
my $sympa_conf = Sympa::Constants::CONFIG;
100
101
102

my %options;
GetOptions(
103
    \%options,
104
    'target=s',
105
    'create:s',    # parameter is optional and only "sympa.conf" is allowed.
106
107
    'batch',
    'display',
108
    'check',
109
110
    'help|h',
    'version|v',
111
112
113
114
);

if ($options{help}) {
    pod2usage();
sikeda's avatar
sikeda committed
115
} elsif ($options{'version'}) {
116
117
    printf "Sympa %s\n", Sympa::Constants::VERSION;
    exit 0;
118
} elsif (defined $options{create}) {
119
    create_configuration();
sikeda's avatar
sikeda committed
120
121
} elsif ($options{display}) {
    display_configuration();
122
123
124
} elsif ($options{check}) {
    check_cpan();
} else {
sikeda's avatar
sikeda committed
125
126
127
128
129
130
131
132
133
134
    my %user_param;
    foreach my $arg (@ARGV) {
        # check for key/values settings
        if ($arg =~ /\A(\w+)=(.+)/) {
            $user_param{$1} = $2;
        } else {
            die "$0: Invalid commandline argument: $arg\n";
        }
    }
    edit_configuration(%user_param);
135
136
137
138
139
}

exit 0;

sub create_configuration {
140
    my $conf;
141
    if ($options{create} eq '' or $options{create} eq 'sympa.conf') {
142
143
144
145
        $conf = $options{target} ? $options{target} : $sympa_conf;
    } else {
        pod2usage("$options{create} is not a valid argument");
        exit 1;
146
    }
147

salaun's avatar
salaun committed
148
    if (-f $conf) {
149
150
        print STDERR "$conf file already exists, exiting\n";
        exit 1;
salaun's avatar
salaun committed
151
    }
152

153
    my $umask = umask 037;
154
    unless (open NEWF, '>', $conf) {
155
        umask $umask;
sikeda's avatar
sikeda committed
156
157
158
        die "$0: "
            . sprintf(gettext("Unable to open %s : %s"), $conf, $ERRNO)
            . "\n";
159
    }
160
    umask $umask;
161

162
    if ($options{create} eq 'sympa.conf') {
163
#        print NEWF <<EOF
164
165
166
167
## Configuration file for Sympa
## many parameters are optional
## refer to the documentation for a detailed list of parameters

168
#EOF
169
    }
170

171
    my $title;
172
    foreach my $param (@Sympa::ConfDef::params) {
173
174
        next if $param->{obsolete};

175
        unless ($param->{'name'}) {
176
            $title = gettext($param->{'gettext_id'})
177
                if $param->{'gettext_id'};
178
179
180
            next;
        }

181
        next unless $param->{'file'};
182
        ##next unless defined $param->{'default'} or defined $param->{'sample'};
183

184
185
186
187
        if ($title) {
            printf NEWF "###\\\\\\\\ %s ////###\n\n", $title;
            undef $title;
        }
188

189
190
191
        printf NEWF "## %s\n", $param->{'name'};

        if ($param->{'gettext_id'}) {
192
193
            print NEWF Sympa::Tools::Text::wrap_text(
                gettext($param->{'gettext_id'}),
194
                '## ', '## ');
195
        }
196

197
198
        print NEWF Sympa::Tools::Text::wrap_text(
            gettext($param->{'gettext_comment'}),
199
200
            '## ', '## ')
            if $param->{'gettext_comment'};
201

202
        if (defined $param->{'sample'}) {
203
            printf NEWF '## ' . gettext('Example: ') . "%s\t%s\n",
204
205
                $param->{'name'}, $param->{'sample'};
        }
206
207
208
209
210
211

        if (defined $param->{'default'}) {
            printf NEWF "#%s\t%s\n", $param->{'name'}, $param->{'default'};
        } elsif ($param->{'optional'}) {
            printf NEWF "#%s\t\n", $param->{'name'};
        } else {
sikeda's avatar
sikeda committed
212
213
            printf NEWF "#%s\t%s\n", $param->{'name'},
                gettext("(You must define this parameter)");
214
        }
215
        print NEWF "\n";
216
217
    }

salaun's avatar
salaun committed
218
219
    close NEWF;
    print STDERR "$conf file has been created\n";
220
221
}

sikeda's avatar
sikeda committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
sub display_configuration {
    die "$0: You must run as superuser.\n"
        if $UID;
    die "$0: Installation of Sympa has not been completed.\n"
        . "Run sympa_wizard.pl --check\n"
        if $modfail;

    # Load sympa config (but not using database)
    unless (defined Conf::load($sympa_conf, 1)) {
        printf STDERR
            "$0: Unable to load sympa configuration, file %s or one of the virtual host robot.conf files contain errors. Exiting.\n",
            $sympa_conf;
        exit 1;
    }

    my ($var, $disp);

    print "[SYMPA]\n";
    foreach my $key (sort keys %Conf::Conf) {
241
242
        next
            if grep { $key eq $_ }
243
            qw(auth_services blocklist crawlers_detection listmasters
244
            locale2charset nrcpt_by_domain robot_by_http_host request
245
            robot_name robots source_file sympa trusted_applications);
246

sikeda's avatar
sikeda committed
247
248
        $var = $Conf::Conf{$key};

249
250
251
252
253
254
255
256
        if ($key eq 'automatic_list_families') {
            $disp = join ';', map {
                my $name = $_;
                join ':', map { sprintf '%s=%s', $_, $var->{$name}{$_} }
                    grep { !/\Aescaped_/ }
                    sort keys %{$var->{$name} || {}};
            } sort keys %{$var || {}};
        } elsif (ref $var eq 'ARRAY') {
sikeda's avatar
sikeda committed
257
258
259
260
261
262
263
264
265
            $disp = join(',', map { defined $_ ? $_ : '' } @$var);
        } else {
            $disp = defined $var ? $var : '';
        }

        printf "%s=\"%s\"\n", $key, $disp;
    }
}

266
sub edit_configuration {
sikeda's avatar
sikeda committed
267
268
269
    my %user_param = @_;

    die "$0: You must run as superuser.\n"
270
        if $UID;
sikeda's avatar
sikeda committed
271
    die "$0: Installation of Sympa has not been completed.\n"
272
273
        . "Run sympa_wizard.pl --check\n"
        if $modfail;
274

275
    # complement required fields.
276
    foreach my $param (@Sympa::ConfDef::params) {
277
        next if $param->{obsolete};
278
        next unless $param->{'name'};
279
        if ($param->{'name'} eq 'domain') {
sikeda's avatar
sikeda committed
280
            $param->{'default'} = Sys::Hostname::hostname();
281
        } elsif ($param->{'name'} eq 'wwsympa_url') {
282
283
            $param->{'default'} = sprintf 'http://%s/sympa',
                Sys::Hostname::hostname();
284
        } elsif ($param->{'name'} eq 'listmaster') {
285
286
            $param->{'default'} = sprintf 'your_email_address@%s',
                Sys::Hostname::hostname();
287
288
        }
    }
289
290
291

    ## Load sympa config (but not using database)
    unless (defined Conf::load($sympa_conf, 1)) {
292
        printf STDERR
293
            "$0: Unable to load sympa configuration, file %s or one of the virtual host robot.conf files contain errors. Exiting.\n",
294
295
            $sympa_conf;
        exit 1;
296
297
    }

298
    my $somechange = 0;
salaun's avatar
 
salaun committed
299

300
301
    my @new_sympa_conf;
    my $title = undef;
sikeda's avatar
sikeda committed
302

303
    # dynamic defaults
304
    my $domain    = Sys::Hostname::hostname();
305
    my $http_host = "http://$domain";
306
307

    ## Edition mode
308
    foreach my $param (@Sympa::ConfDef::params) {
309
310
        next if $param->{obsolete};

311
        unless ($param->{'name'}) {
312
            $title = gettext($param->{'gettext_id'})
313
                if $param->{'gettext_id'};
314
            next;
315
        }
316

317
318
        my $file  = $param->{'file'};
        my $name  = $param->{'name'};
319
        my $query = $param->{'gettext_id'} || '';
320
        $query = gettext($query) if $query;
321
        my $advice = $param->{'gettext_comment'};
322
        $advice = gettext($advice) if $advice;
323
324
        my $sample = $param->{'sample'};
        my $current_value;
325

326
        next unless $file;
327
        if ($file eq 'sympa.conf' or $file eq 'wwsympa.conf') {
328
            $current_value = $Conf::Conf{$name};
329
            $current_value = '' unless defined $current_value;
330
        } else {
331
            next;
332
        }
333
334
335
336
337
338
339
340

        if ($title) {
            ## write to conf file
            push @new_sympa_conf,
                sprintf "###\\\\\\\\ %s ////###\n\n", $title;
        }

        my $new_value = '';
341
342
343
344
345
        if ($options{batch}) {
            if (exists $user_param{$name}) {
                $new_value = $user_param{$name};
            }
        } elsif ($param->{'edit'} and $param->{'edit'} eq '1') {
346
            print "\n\n** $title **\n" if $title;
347

348
            print "\n";
349
350
351
            print Sympa::Tools::Text::wrap_text($query || '', '* ', '  ');
            print Sympa::Tools::Text::wrap_text($advice, '  ... ', '  ')
                if $advice;
352
            printf(gettext('%s [%s] : '), $name, $current_value);
353
            $new_value = <STDIN>;
354
355
356
357
358
359
            chomp $new_value;
        }
        if ($new_value eq '') {
            $new_value = $current_value;
        }

360
        undef $title;
361
362

        ## Skip empty parameters
363
        next if $new_value eq '' and !$sample;
364
365
366

        ## param is an ARRAY
        if (ref($new_value) eq 'ARRAY') {
367
            $new_value = join ',', @{$new_value};
368
369
        }

370
        unless ($file eq 'sympa.conf' or $file eq 'wwsympa.conf') {
371
            printf STDERR gettext("Incorrect parameter definition: %s\n"),
372
                $file;
373
374
375
376
377
        }

        if ($new_value eq '') {
            next unless $sample;

378
379
            push @new_sympa_conf,
                Sympa::Tools::Text::wrap_text($query, '## ', '## ');
380

381
            if (defined $advice and length $advice) {
382
383
                push @new_sympa_conf,
                    Sympa::Tools::Text::wrap_text($advice, '## ', '## ');
384
385
            }

386
            push @new_sympa_conf, "# $name\t$sample\n\n";
387
        } else {
388
389
            push @new_sympa_conf,
                Sympa::Tools::Text::wrap_text($query, '## ', '## ');
390
            if (defined $advice and length $advice) {
391
392
                push @new_sympa_conf,
                    Sympa::Tools::Text::wrap_text($advice, '## ', '## ');
393
394
395
            }

            if ($current_value ne $new_value) {
396
                push @new_sympa_conf, "# was $name $current_value\n";
397
398
399
                $somechange = 1;
            }

400
            push @new_sympa_conf, "$name\t$new_value\n\n";
401
        }
salaun's avatar
 
salaun committed
402
    }
403

404
    if ($somechange) {
405
406
407
        my @time = localtime time;
        my $date = sprintf '%d%02d%02d%02d%02d%02d',
            $time[5] + 1900, $time[4] + 1, @time[3, 2, 1, 0];
408

409
        ## Keep old config file
410
        unless (rename $sympa_conf, $sympa_conf . '.' . $date) {
411
412
            warn sprintf(gettext("Unable to rename %s : %s"),
                $sympa_conf, $ERRNO);
413
414
        }

415
        ## Write new config file
416
        my $umask = umask 037;
417
        unless (open(SYMPA, "> $sympa_conf")) {
418
            umask $umask;
sikeda's avatar
sikeda committed
419
420
421
422
            die "$0: "
                . sprintf(gettext("Unable to open %s : %s"),
                $sympa_conf, $ERRNO)
                . "\n";
423
        }
424
        umask $umask;
425
426
        chown [getpwnam(Sympa::Constants::USER)]->[2],
            [getgrnam(Sympa::Constants::GROUP)]->[2], $sympa_conf;
427
428
429
430

        print SYMPA @new_sympa_conf;
        close SYMPA;

431
432
433
        printf gettext(
            "%s have been updated.\nPrevious versions have been saved as %s.\n"
        ), $sympa_conf, "$sympa_conf.$date";
salaun's avatar
 
salaun committed
434
    }
435
}
436

437
sub check_cpan {
438
439
    my %cpan_modules = CPANFile::load() or die;

440
441
    print gettext(
        "##############################################################################
442
443
# This process will help you install all Perl (CPAN) modules required by Sympa
# software.
444
445
# Sympa requires from 50 to 65 additional Perl modules to run properly. 
# The whole installation process should take around 15 minutes.
446
447
448
449
450
451
452
# You'll first have to configure the CPAN shell itself and select your
# favourite CPAN server.
# Note that you might prefer to install the required Perl modules using your
# favourite DEB/RPM mechanism.
# Feel free to interrupt the process if needed ; you can restart it safely
# afterward.
##############################################################################
453
454
Press the Enter key to continue..."
    ) . "\n";
455
456
    my $rep = <STDIN>;

457
458
    print "\n";

459
460
461
462
463
464
465
466
467
468
469
    # Choose default DBD module if it has not been defined.
    my $db_type;
    if (open my $fh, '<', $sympa_conf) {
        foreach my $line (<$fh>) {
            if ($line =~ /\Adb_type\s+(\S*)/) {
                $db_type = $1;
            }
        }
        close $fh;
    }
    if ($db_type
470
471
        and exists $cpan_modules{'DBD::' . $db_type}) {
        $cpan_modules{'DBD::' . $db_type}->{mandatory} = 1;
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
    } else {
        my @dbd = (
            'MySQL/MariaDB' => 'DBD::mysql',
            'PostgreSQL'    => 'DBD::Pg',
            'SQLite'        => 'DBD::SQLite',
            'Oracle'        => 'DBD::Oracle',
        );
        my $selected;
        while (1) {
            print "\n"
                . gettext('Which RDBMS will you use for core database:')
                . "\n";
            for (my $i = 0; $i < scalar @dbd; $i += 2) {
                printf "%d: %s\n", $i / 2 + 1, $dbd[$i];
            }
            printf gettext('-> Select RDBMS [1-%d] '), scalar @dbd / 2;
sikeda's avatar
sikeda committed
488
            $selected = <STDIN>;
489
490
491
            chomp $selected;
            last
                if $selected =~ /\A\d+\z/
492
493
                and 0 < $selected
                and $selected * 2 <= scalar @dbd;
494
        }
495
        $cpan_modules{$dbd[$selected * 2 - 1]}->{mandatory} = 1;
496
497
    }

498
    ### REQ perl version
499
    print "\n" . gettext('Checking for PERL version:') . "\n\n";
500
501
502
    # Compat. for perl < 5.10: $^V is not an object but a vector of integers.
    my $rpv = eval 'v' . $cpan_modules{"perl"}{'required_version'} or die $@;
    if ($^V ge $rpv) {
503
        printf gettext('Your version of perl is OK (%s  >= %s)') . "\n", $],
504
            $cpan_modules{"perl"}{'required_version'};
505
    } else {
506
507
        printf gettext(
            "Your version of perl is TOO OLD (%s  < %s)\nPlease INSTALL a new one !"
508
        ) . "\n", $], $cpan_modules{"perl"}{'required_version'};
509
510
    }

511
    print "\n" . gettext('Checking for REQUIRED modules:') . "\n\n";
512
    check_modules('y', \%cpan_modules, 'mandatory');
513
    print "\n" . gettext('Checking for OPTIONAL modules:') . "\n\n";
514
    check_modules('n', \%cpan_modules, 'optional');
515

516
517
    print gettext(
        "******* NOTE *******
518
You can retrieve all theses modules from any CPAN server
519
520
(for example ftp://ftp.pasteur.fr/pub/computing/CPAN/CPAN.html)"
    ) . "\n";
521
522
###--------------------------
# reports modules status
523
524
# $cpan_modules is the cpan_modules structure
# $type is the type of modules (mandatory | optional) that should be installed
525
526
527
528
###--------------------------
}

sub check_modules {
529
#    my($default, $todo, $versions, $opt_features) = @_;
530
    my ($default, $cpan_modules, $type) = @_;
531

532
533
    printf "%s%s\n", gettext('perl module', -32), gettext('STATUS');
    printf "%-32s%s\n", gettext('-----------'), gettext('------');
534

535
    foreach my $mod (sort keys %$cpan_modules) {
536
537
538
539
540
541
542
543
544
545
546

        ## Only check modules of the expected type
        if ($type eq 'mandatory') {
            next unless ($cpan_modules->{$mod}{mandatory});
        } elsif ($type eq 'optional') {
            next if ($cpan_modules->{$mod}{mandatory});
        }

        ## Skip perl itself to prevent a huge upgrade
        next if ($mod eq 'perl');

547
        printf "%-32s", $mod;
548

549
        eval "require $mod";
550
        if ($EVAL_ERROR) {
551
            ### not installed
552
            print gettext('was not found on this system.') . "\n";
553
            install_module($mod, {'default' => $default}, $cpan_modules);
554
        } else {
555
            my ($vs, $v);
556
557
558
559
            $vs = "$mod" . "::VERSION";
            {
                no strict 'refs';
                $v = $$vs;
560
561
562
563
564
            }

            my $rv = $cpan_modules->{$mod}{required_version} || "1.0";
            ### OK: check version
            if ($v ge $rv) {
565
                printf gettext('OK (%-6s >= %s)') . "\n", $v, $rv;
566
567
                next;
            } else {
568
569
570
571
                printf gettext('version is too old (%s < %s)') . "\n", $v,
                    $rv;
                printf gettext(
                    '>>>>>>> You must update "%s" to version "%s" <<<<<<.')
572
                    . "\n", $mod, $rv;
573
574
                install_module($mod, {'default' => $default}, $cpan_modules);
            }
575
        }
salaun's avatar
 
salaun committed
576
577
578
    }
}

579
580
581
582
##----------------------
# Install a CPAN module
##----------------------
sub install_module {
583
584
585
    return unless $with_CPAN;

    my ($module, $options, $cpan_modules) = @_;
salaun's avatar
 
salaun committed
586

587
    my $default = $options->{'default'};
salaun's avatar
salaun committed
588

sikeda's avatar
sikeda committed
589
    unless ($ENV{'FTP_PASSIVE'} and $ENV{'FTP_PASSIVE'} eq 1) {
590
591
        $ENV{'FTP_PASSIVE'} = 1;
        print "Setting FTP Passive mode\n";
salaun's avatar
 
salaun committed
592
    }
salaun's avatar
salaun committed
593

594
595
596
597
598
599
    # This is required on RedHat 9 for DBD::mysql installation
    my $lang;
    if ($ENV{'LANG'} and $ENV{'LANG'} =~ /UTF-8/) {
        $lang = $ENV{'LANG'};
        $ENV{'LANG'} = 'C';
    }
600
601

    unless ($EUID == 0) {
602
603
604
605
606
        printf gettext('## You need root privileges to install %s module. ##')
            . "\n", $module;
        print gettext(
            '## Press the Enter key to continue checking modules. ##')
            . "\n";
607
608
        my $t = <STDIN>;
        return undef;
salaun's avatar
 
salaun committed
609
    }
salaun's avatar
salaun committed
610

611
    unless ($options->{'force'}) {
612
        print Sympa::Tools::Text::wrap_text(
613
614
615
616
617
618
            sprintf(
                gettext('-> Usage of this module: %s') . "\n",
                gettext($cpan_modules->{$module}{'gettext_id'})
            ),
            '', '   '
        ) if ($cpan_modules->{$module}{'gettext_id'});
619
        print Sympa::Tools::Text::wrap_text(
620
621
622
623
624
625
            sprintf(
                gettext('-> Prerequisites: %s') . "\n",
                gettext($cpan_modules->{$module}{'gettext_comment'})
            ),
            '', '   '
        ) if ($cpan_modules->{$module}{'gettext_comment'});
626
        printf gettext('-> Install module %s ? [%s] '), $module, $default;
627
628
        my $answer = <STDIN>;
        chomp $answer;
629
630
631
        $answer ||= $default;
        return unless ($answer =~ /^y$/i);
    }
632

633
634
635
636
637
638
639
640
641
642
643
    $CPAN::Config->{'inactivity_timeout'} =
        0;   ## disable timeout to prevent timeout during modules installation
    $CPAN::Config->{'colorize_output'} = 1;
    $CPAN::Config->{'build_requires_install_policy'} =
        'yes';    ## automatically installed prerequisites without asking
    $CPAN::Config->{'prerequisites_policy'} =
        'follow';    ## build prerequisites automatically
    $CPAN::Config->{'load_module_verbosity'} =
        'none';      ## minimum verbosity during module loading
    $CPAN::Config->{'tar_verbosity'} =
        'none';      ## minimum verbosity with tar command
644

sikeda's avatar
sikeda committed
645
646
647
648
649
650
651
652
653
    # CPAN::Shell->clean($module) if ($options->{'force'});

    # CPAN::Shell->make($module);
    # if ($options->{'force'}) {
    #     CPAN::Shell->force('test', $module);
    # } else {
    #     CPAN::Shell->test($module);
    # }
    # # Could use CPAN::Shell->force('install') if make test failed
654
    CPAN::Shell->install($module);
655
656

    ## Check if module has been successfuly installed
657
    unless (eval "require $module") {
658
659
660

        ## Prevent recusive calls if already in force mode
        if ($options->{'force'}) {
661
662
663
            printf gettext(
                "Installation of %s still FAILED. You should download the tar.gz from http://search.cpan.org and install it manually."
            ), $module;
664
            my $answer = <STDIN>;
665
        } else {
666
667
668
            printf gettext(
                'Installation of %s FAILED. Do you want to force the installation of this module? (y/N) '
            ), $module;
669
670
            my $answer = <STDIN>;
            chomp $answer;
671
            if ($answer =~ /^y/i) {
672
                install_module($module, {'force' => 1}, $cpan_modules);
673
674
675
            }
        }
    }
salaun's avatar
 
salaun committed
676

677
678
    # Restore lang
    $ENV{'LANG'} = $lang if $lang;
679
}
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729

package CPANFile;

use lib '--modulesdir--';
use strict;
use warnings;

our $description;
our $is_optional;
my %cpan_modules;

sub feature {
    shift;
    local $description = shift;
    local $is_optional = 1;
    shift->();
}

sub on {
    return unless shift eq 'runtime';
    shift->();
}

sub recommends {
    local $is_optional = 1;
    _depends(@_);
}

sub requires {
    _depends(@_);
}

sub load {
    do 'cpanfile';
    %cpan_modules;
}

sub _depends {
    my $module = shift;
    my $verreq = shift || '0';
    $verreq = [grep { !/[!<]/ } split /\s*,\s*/, $verreq]->[0];
    $verreq =~ s/\A[\s=>]+//;
    $cpan_modules{$module} = {
        required_version => $verreq,
        ($is_optional ? () : (mandatory => 1)),
        ($description ? (gettext_id => $description) : ()),
    };
}

1;
730
731
732
733
734
735
736
737
738
739
__END__

=encoding utf-8

=head1 NAME

sympa_wizard, sympa_wizard.pl - Help Performing Sympa Initial Setup
    
=head1 SYNOPSIS

740
741
742
743
744
745
746
C<sympa_wizard.pl>
S<[ C<--batch> [ I<key>=I<value> ... ] ]>
S<[ C<--check> ]>
S<[ C<--create> [ C<--target=>I<file> ] ]>
S<[ C<--display> ]>
S<[ C<-h, --help> ]>
S<[ C<-v, --version> ]>
747
748
749
750
751

=head1 OPTIONS

=over 4

752
=item C<sympa_wizard.pl>
753
754
755

Edit current Sympa configuration.

756
=item C<sympa_wizard.pl> C<--batch> I<key>=I<value> ...
sikeda's avatar
sikeda committed
757
758
759
760

Edit in batch mode.
Arguments would include pairs of parameter name and value.

761
=item C<sympa_wizard.pl> C<--check>
762
763
764

Check CPAN modules needed for running Sympa.

765
=item C<sympa_wizard.pl> C<--create> [ C<--target> I<file> ]
766
767
768

Creates a new F<sympa.conf> configuration file.

769
=item C<sympa_wizard.pl> C<--display>
sikeda's avatar
sikeda committed
770
771
772

Outputs all configuration parameters.

773
=item C<sympa_wizard.pl> C<--help>
774
775
776

Display usage instructions.

777
=item C<sympa_wizard.pl> C<--version>
778
779
780
781
782

Print version number.

=back

sikeda's avatar
sikeda committed
783
784
785
=head1 HISTORY

This program was originally written by:
786
787
788
789
790
791
792
793
794

=over 4

=item Serge Aumont <sa@cru.fr>

=item Olivier SalaE<252>n <os@cru.fr>

=back

sikeda's avatar
sikeda committed
795
796
C<--batch> and C<--display> options are added on Sympa 6.1.25 and 6.2.15.

797
=cut