sympa_wizard.pl.in 23.2 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
14
# Copyright 2018 The Sympa Community. See the AUTHORS.md file at the
# top-level directory of this distribution and at
# <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
244
245
246
247
            qw(auth_services blacklist cas_number crawlers_detection
            generic_sso_number ldap ldap_number listmasters
            locale2charset nrcpt_by_domain robot_by_http_host request
            robot_name robots source_file sympa trusted_applications
            use_passwd);
248

sikeda's avatar
sikeda committed
249
250
        $var = $Conf::Conf{$key};

251
252
253
254
255
256
257
258
        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
259
260
261
262
263
264
265
266
267
            $disp = join(',', map { defined $_ ? $_ : '' } @$var);
        } else {
            $disp = defined $var ? $var : '';
        }

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

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

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

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

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

300
    my $somechange = 0;
salaun's avatar
 
salaun committed
301

302
303
    my @new_sympa_conf;
    my $title = undef;
sikeda's avatar
sikeda committed
304

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

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

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

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

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

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

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

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

362
        undef $title;
363
364

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

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

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

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

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

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

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

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

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

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

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

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

        print SYMPA @new_sympa_conf;
        close SYMPA;

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

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

442
443
    print gettext(
        "##############################################################################
444
445
# This process will help you install all Perl (CPAN) modules required by Sympa
# software.
446
447
# Sympa requires from 50 to 65 additional Perl modules to run properly. 
# The whole installation process should take around 15 minutes.
448
449
450
451
452
453
454
# 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.
##############################################################################
455
456
Press the Enter key to continue..."
    ) . "\n";
457
458
    my $rep = <STDIN>;

459
460
    print "\n";

461
462
463
464
465
466
467
468
469
470
471
    # 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
472
473
        and exists $cpan_modules{'DBD::' . $db_type}) {
        $cpan_modules{'DBD::' . $db_type}->{mandatory} = 1;
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
    } 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
490
            $selected = <STDIN>;
491
492
493
            chomp $selected;
            last
                if $selected =~ /\A\d+\z/
494
495
                and 0 < $selected
                and $selected * 2 <= scalar @dbd;
496
        }
497
        $cpan_modules{$dbd[$selected * 2 - 1]}->{mandatory} = 1;
498
499
    }

500
    ### REQ perl version
501
    print "\n" . gettext('Checking for PERL version:') . "\n\n";
502
503
504
    # 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) {
505
        printf gettext('Your version of perl is OK (%s  >= %s)') . "\n", $],
506
            $cpan_modules{"perl"}{'required_version'};
507
    } else {
508
509
        printf gettext(
            "Your version of perl is TOO OLD (%s  < %s)\nPlease INSTALL a new one !"
510
        ) . "\n", $], $cpan_modules{"perl"}{'required_version'};
511
512
    }

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

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

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

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

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

        ## 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');

549
        printf "%-32s", $mod;
550

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

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

582
583
584
585
##----------------------
# Install a CPAN module
##----------------------
sub install_module {
586
587
588
    return unless $with_CPAN;

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

590
    my $default = $options->{'default'};
salaun's avatar
salaun committed
591

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

597
598
599
600
601
602
    # 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';
    }
603
604

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

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

636
637
638
639
640
641
642
643
644
645
646
    $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
647

sikeda's avatar
sikeda committed
648
649
650
651
652
653
654
655
656
    # 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
657
    CPAN::Shell->install($module);
658
659

    ## Check if module has been successfuly installed
660
    unless (eval "require $module") {
661
662
663

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

680
681
    # Restore lang
    $ENV{'LANG'} = $lang if $lang;
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
730
731
732

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;
733
734
735
736
737
738
739
740
741
742
__END__

=encoding utf-8

=head1 NAME

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

743
744
745
746
747
748
749
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> ]>
750
751
752
753
754

=head1 OPTIONS

=over 4

755
=item C<sympa_wizard.pl>
756
757
758

Edit current Sympa configuration.

759
=item C<sympa_wizard.pl> C<--batch> I<key>=I<value> ...
sikeda's avatar
sikeda committed
760
761
762
763

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

764
=item C<sympa_wizard.pl> C<--check>
765
766
767

Check CPAN modules needed for running Sympa.

768
=item C<sympa_wizard.pl> C<--create> [ C<--target> I<file> ]
769
770
771

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

772
=item C<sympa_wizard.pl> C<--display>
sikeda's avatar
sikeda committed
773
774
775

Outputs all configuration parameters.

776
=item C<sympa_wizard.pl> C<--help>
777
778
779

Display usage instructions.

780
=item C<sympa_wizard.pl> C<--version>
781
782
783
784
785

Print version number.

=back

sikeda's avatar
sikeda committed
786
787
788
=head1 HISTORY

This program was originally written by:
789
790
791
792
793
794
795
796
797

=over 4

=item Serge Aumont <sa@cru.fr>

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

=back

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

800
=cut