aboutsummaryrefslogtreecommitdiff
path: root/install.pl
blob: 0bcc464d1ca7df8662430079493c6405e1f37af7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
use strict;
use Getopt::Long;
use File::Basename;
use File::Copy;
use File::Find;
use File::Path qw(make_path);
use Pod::Usage;
use Pod::Man;
use Data::Dumper;

=head1 NAME

install.pl - install Puszcza-specific Mailman extensions

=head1 SYNOPSIS

B<perl install.pl>
[B<-D> I<DIR>]
[B<-n>]    
[B<--destdir=>I<DIR>]
[B<--htdocs-dir=>I<DIR>]
[B<--dry-run>]
I<MAILMAN-DIR>
[I<DIR>...]

=head1 DESCRIPTION    

Installs Puszcza extensions to Mailman.  This includes the B<mail.gnu.org.ua>
site, backend scripts for conversion to HTML and indexing, and B<listarchive>
CGI script.

The I<MAILMAN-DIR> argument should point to B<Mailman> source directory. This
is a directory from where you installed B<Mailman>, in other words,
B<configure> and B<make install> should have already been run in it by the
time you run B<install.pl>. Also, this directory should be writable.

Optional I<DIR> arguments select specific components to install.

=head1 OPTIONS

=over 4

=item B<-D>, B<--destdir=>I<DIR>

Destination directory.  This has the same meaning as B<DESTDIR> variable in
automake-generated makefiles.    
    
=item B<-n>, B<--dry-run>

Do nothing, print what would have been done.    

=item B<--htdocs-dir=>I<DIR>

Installation directory for the B<mail.gnu.org.ua> site.  Defaults to
F<B<MAILMAN>/htdocs>, where B<MAILMAN> is Mailman installation prefix.    

=cut    
    
my $progname;
my $progdescr = "install Puszcza-specific Mailman extensions";
my $dry_run;
my $destdir;
my $mailmandir;
my $htdocsdir;

sub expvar {
    my ($vtab, $name, $f, $t) = @_;
    my $val = $vtab->{$name};
    return '' unless defined $val;
    if (defined($f)) {
	$val = join(' ', map { s/$f$/$t/; $_ } split(/\s+/, $val));
    }
    return $val;
}

sub parse_makefile_vars {
    my $file = shift;
    my %vtab;

    open(my $fd, '<', $file) or die "can't open $file: $!";
    while (<$fd>) {
        chomp;

        if (/\\$/) {
            chop;
            $_ .= <$fd>;
            redo;
        }

        s/\s+$//;
        s/#.*//;
        next if ($_ eq "");

	if (/^([a-zA-Z0-9_]+)\s*=\s*(.*)$/) {
	    $vtab{$1} = $2;
	    $vtab{$1} =~ s/\$\(([a-zA-Z0-9_]+)(?::([^)=]+)=([^)]+))?\)/expvar(\%vtab, $1, $2, $3)/gex;
	}
    }
    close($fd);
    return %vtab;
}

# ##

sub runcmd {
    my ($cmd, $res) = @_;
    system($cmd);
    die "failed to execute \"$cmd\": $!" if ($? == -1);
    die "\"$cmd\" died with signal " . ($? & 127) if ($? & 127);
    die "\"$cmd\" exited with code " . ($? >> 8) if ($? >> 8);
}

sub install {
    my ($src, $dst) = @_;
    print "$progname: Installing $src to $dst\n";
    find(sub {
               return if /~$/;	
	       my $dir = $File::Find::dir;
	       my $target;
	       if ($dir eq $src) {
		   $target = "$dst/$_";
	       } else {
		   $dir =~ s#^$src/##;
		   $target = "$dst/$dir/$_";
	       }
	       if (-d $_) {
		   unless (-d $target) {
		       print "$progname: creating $target\n";
		       make_path($target) unless $dry_run;
		   }
	       } else {
		   print "$progname: cp $_ $target\n";
		   unless ($dry_run or copy($_, $target)) {
		       print STDERR "error copying file: $!\n"
		   }
	       }
	 }, $src);
}

sub dir_src {
    my $dir = shift;
    $dir = "$mailmandir/$dir";
    die "$dir does not exist or is not a directory" unless -d $dir;
    die "$dir is not writable" unless -d $dir;
    my $opt = '-n' if $dry_run;
    $opt .= " DESTDIR=\"$destdir\"" if defined($destdir);
    print "$progname: building and installing listarchive\n";
    runcmd("make -C $dir $opt CGI_PROGS=listarchive listarchive");
    runcmd("make -C $dir $opt CGI_PROGS=listarchive MAIL_PROGS= install");
}

sub dest {
    my ($dir, $var) = @_;
    my %vtab = parse_makefile_vars("$dir/Makefile");
    die "$var not defined in $dir/Makefile"
	unless exists $vtab{$var};
    my $dest = $vtab{$var};
    $dest = "$destdir/$dest" if defined($destdir);
    return $dest;
}

sub dir_default {
    my ($base, $ref) = @_;
    my $dir = "$mailmandir/$base";
    die "$dir does not exist or is not a directory" unless -d $dir;
    install($base, dest($dir, $ref->{var}));
}

sub dir_htdocs {
    my ($base, $ref) = @_;
    my $dest;
    if (defined($htdocsdir)) {
	$dest = $htdocsdir;
    } else {
	my %vtab = parse_makefile_vars("$mailmandir/Makefile");
	die "prefix not defined in $mailmandir/Makefile"
	    unless exists $vtab{prefix};
	$dest = "$vtab{prefix}/$base";
	$dest = "$destdir/$dest" if defined($destdir);
    }
    install($base, $dest);
}

sub dir_man {
    my ($base, $ref) = @_;
    my $dest;
    my %vtab = parse_makefile_vars("$mailmandir/Makefile");
    die "prefix not defined in $mailmandir/Makefile"
	unless exists $vtab{prefix};
    $dest = "$vtab{prefix}/$base";
    $dest = "$destdir/$dest" if defined($destdir);
    print "$progname: Installing $base to $dest\n";
    for (my $i = 1; $i <= 8; ++$i) {
	my @files = map { s#$base/##; $_ } glob "$base/*.$i";
	next unless $#files >= 0;
	my $d = "$dest/man$i";
	make_path($d) unless -d $d;
	foreach my $f (@files) {
	    print "$progname: cp $f $d/$f\n";
	    unless ($dry_run or copy("$base/$f", "$d/$f")) {
		print STDERR "error copying file: $!\n"
	    }
	}
    }
}

my %dirs = (
    'src' => { proc => \&dir_src },
    'Mailman' => { proc => \&dir_default, var => 'PACKAGEDIR' },
    'templates' => { proc => \&dir_default, var => 'TEMPLATEDIR' }, 
    'bin' => { proc => \&dir_default, var => 'SCRIPTSDIR' },
    'man' => { proc => \&dir_man },
    'htdocs' => { proc => \&dir_htdocs }
);
# ##
$progname = basename($0);
GetOptions("h" => sub {
                    pod2usage(-message => "$progname: $progdescr",
			      -exitstatus => 0);
           },
           "help" => sub {
                    pod2usage(-verbose => 2, -exitstatus => 0);
           },
           "usage" => sub {
                    pod2usage(-verbose => 0, -exitstatus => 0);
           },
	   "destdir|D=s" => \$destdir,
	   "htdocs-dir=s" => \$htdocsdir,
	   "dry-run|n" => \$dry_run) or exit(1);
    
die "bad number of arguments" unless $#ARGV>=0;

$mailmandir = shift @ARGV;

die "$mailmandir does not exist or is not a directory" unless -d $mailmandir;

@ARGV = ('src',
	 'Mailman',
	 'templates',
	 'bin',
	 'man',
	 'htdocs') if ($#ARGV == -1);
    
foreach my $arg (@ARGV) {
    die "unknown source: $arg" unless exists $dirs{$arg};
    my $v = $dirs{$arg};
    &{$v->{proc}}($arg, $v);
}


    

Return to:

Send suggestions and report system problems to the System administrator.