8 use Digest::MD5 'md5_hex';
10 our (@local_rdomains,@local_rhosts);
12 $ENV{PATH} .= ':/sbin:/usr/sbin';
14 $usage = "usage: $0 [-p port] [IP-address]\n";
15 $xinetd = '/etc/xinetd.d/fex';
20 die "you must be root to install F*EX\n";
23 $fex = 'fex.rus.uni-stuttgart.de';
24 if (system("host $fex >/dev/null") != 0) {
25 die "host $fex is not resolvable - check /etc/resolv.conf\n";
30 if (open $xinetd,$xinetd) {
32 if (/^\s*port\s*=\s*(\d+)/) {
33 $opt_p = $fexport = $1;
35 if (/^\s*bind\s*=\s*([\d.]+)$/) {
42 goto INSTALL if $0 =~ /upgrade$/;
44 if (`uname` =~ /^SunOS/) {
45 die "Solaris is currently not supported. "
46 ."Please contact framstag\@rus.uni-stuttgart.de for details.\n";
49 getopts('p:') or die $usage;
52 if ($arg and -f "locale/$arg/lib/fup.pl") {
53 exec 'locale/translate',$arg;
55 $ip = $arg || $fexip || 0;
58 # if (not $ip and open P,"ifconfig 2>/dev/null |") {
59 if (not $ip and open P,'host $(hostname)|') {
62 if (/(\d+\.\d+\.\d+\.\d+)/) {
69 print "Your IP [$guessed_ip] : ";
76 ($hostname) = gethostbyaddr(gethostbyname($ip),AF_INET);
77 die "cannot find hostname for IP $ip\n" unless $hostname;
79 print "checking prerequisites\n";
81 if (`which xinetd` =~ m{^/}) {
82 print "found xinetd\n";
84 print "xinetd executable NOT found\n";
88 foreach (qw'/usr/lib/sendmail /usr/sbin/sendmail') {
91 print "found $sendmail\n";
96 print "sendmail NOT found\n";
101 print "installation aborted, nothing has been touched yet\n";
102 print "what now? ==> see doc/installation\n";
108 $SH = IO::Socket::INET->new(
115 print "There is already a tcp-service running on $ip:$opt_p !\n";
116 print "Select another port for F*EX by running $0 -p OTHERPORT $ip\n";
117 print "or an alternative IP-address by running $0 OTHERADDRESS\n";
122 print "prerequisites checked, ok\n";
124 unless (getpwnam('fex')) {
125 print "creating user fex\n";
126 system 'useradd -s /bin/bash -c "File EXchange" -m fex';
130 if (open F,'/etc/passwd') {
132 $fexbash = $_ if /^fex:.*\/bash/;
137 die "no bash login shell for user fex\n";
144 @FEX = getpwnam('fex') or die "no user fex\n";
146 $ENV{HOME} = $FEXHOME; # needed for later eval fex.ph
148 die "no HOME directory for user fex\n" unless -d $FEXHOME;
149 if ($FEXHOME !~ /fex/) {
150 print "HOME=$FEXHOME for user fex does not contain \"fex\"\n";
151 print "REALLY continue?! ";
156 print "Installing:\n";
158 $pecl = "$FEXHOME/perl/Encode/ConfigLocal.pm";
160 mkdir "$FEXHOME/perl";
161 mkdir "$FEXHOME/perl/Encode";
162 open $pecl,'>',$pecl or die "$0: cannot write $pecl - $!\n";
164 "# hack for broken Perl in SuSe and Solaris, used via \@INC in fexsrv\n",
168 chownr('fex:root',"$FEXHOME/perl");
174 "lib/reactivation.txt",
178 "htdocs/FAQ/local.faq",
185 rename $f,$fs and print "$f --> $fs\n";
189 cpav(qw'bin cgi-bin lib etc htdocs doc',$FEXHOME);
190 unlink "$FEXHOME/doc/License";
191 unlink "$FEXHOME/htdocs/License";
193 $hl = "$FEXHOME/htdocs/locale";
194 unless (-d $hl) { mkdir $hl or die "$0: cannot mkdir $hl - $!\n" }
202 rename $f,$fn and print "$f --> $fn\n";
203 rename $fs,$f and print "$fs --> $f\n";
207 if (-d "$FEXHOME/spool") {
208 warn "checking $FEXHOME/spool ...\n";
211 $newinstall = $FEXHOME;
213 mkdir "$FEXHOME/spool",0700 or die "cannot mkdir $FEXHOME/spool - $!\n";
214 mkdir "$FEXHOME/spool/.error",0700;
216 chownr('fex',"$FEXHOME/spool/.");
219 if (open my $setup,'/root/bin/setup') {
226 system(qw'perl -p -i -e',
227 's:href="/?FAQ.html":href="/FAQ/FAQ.html":',
228 "$FEXHOME/lib/fup.pl"
231 $fph = "$FEXHOME/lib/fex.ph";
232 open $fph,$fph or die "cannot read $fph - $!\n";
234 s/'MYHOSTNAME.MYDOMAIN'/'$hostname'/;
241 # die "no \$spooldir in $fph\n" unless $spooldir;
242 $spooldir ||= '/home/fex/spool';
243 die "\$spooldir=$spooldir is not a directory, see $fph\n" unless -d $spooldir;
244 symlink $spooldir,"$FEXHOME/spool" unless -e "$FEXHOME/spool";
245 @sds1 = stat "$spooldir/.";
246 @sds2 = stat "$FEXHOME/spool/.";
247 if ("@sds1" ne "@sds2") {
248 die "$FEXHOME/spool is not a symbolic link to \$spooldir=$spooldir\n";
251 $fid = "$FEXHOME/.fex/id";
252 $aa = "$spooldir/$admin/@";
254 if ($newinstall or not -s $aa) {
257 print "Server hostname [$hostname] : ";
260 $hostname = $_ if $_;
261 last if gethostbyname($hostname);
262 print "No DNS for $hostname\n";
265 print "F*EX admin [$admin] : ";
269 last if $admin =~ /.\@./;
270 print "admin must be a valid email address!\n";
272 $aa = "$spooldir/$admin/@";
273 while (not $admin_pw) {
274 print "F*EX admin password: ";
276 $admin_pw =~ s/\s//g;
279 print "(admin password is in $aa)\n";
280 $conf =~ s/^\s*\$hostname\s*=.*/\$hostname = '$hostname';/m;
281 $conf =~ s/^\s*\$admin\s*=.*/\$admin = '$admin';/m;
284 print "\nFound old \$admin_pw in $fph !\n";
285 print "This is no longer supported for security reason.\n";
290 if ($_ ne $admin_pw) {
291 print "\nYou have to delete \$admin_pw in $fph and run\n";
292 print "$FEXHOME/bin/fac -u $admin $admin_pw\n";
293 print "\nThen rerun $0\n";
298 print "\$admin_pw is transfered to auth-ID in $aa\n\n";
299 $conf =~ s/^\s*(\$admin_pw)\s*=.*/# $1 is now auth_ID of user \$admin/m;
303 open $fph,">$fph.new" or die "$0: cannot write $fph.new - $!\n";
306 system "chown fex $fph.new";
307 rename "$fph.new",$fph or die "$0: cannot rename $fph.new to $fph - $!\n";
309 do $fph or die "$0: error in new $fph - $!\n";
311 if (@locales = glob "locale/*/lib/fup.pl") {
313 m{locale/(.+?)/} and $locale = $1;
314 if (-f "$FEXHOME/$_") {
315 system 'locale/translate',$locale;
316 chownr('fex',"$FEXHOME/locale/$locale");
317 $hl = "$FEXHOME/htdocs/locale/$locale";
318 symlink "$FEXHOME/locale/$locale/htdocs",$hl unless -l $hl;
320 push @nlocales,"./install $1\n";
324 if (glob "$FEXHOME/locale/*/lib/fup.pl") {
325 print "\nTo install another localized version, type:\n";
327 print "\nTo install a localized version, type:\n";
333 $fph = "$FEXHOME/lib/fex.ph";
336 unless (-f $xinetd) {
337 my $xc = '/etc/xinetd.conf';
340 if (/^\s*only_from/) {
341 print "WARNING: found \"only_from\" in $xc : fexsrv is restricted!\n";
346 if (-d '/etc/xinetd.d') {
347 unless (-f $xinetd) {
348 open $xinetd,">$xinetd" or die "cannot write $xinetd - $!\n";
349 open F,'etc/xinetd_fex' or die "cannot read etc/xinetd_fex - $!\n";
358 system qw'/etc/init.d/xinetd restart';
359 print "WARNING: cannot restart xinetd\n" if $?;
362 print "WARNING: No /etc/xinetd.d found.\n";
363 print "WARNING: You have to install etc/xinetd_fex manually.\n";
366 $crontab = `crontab -u fex -l 2>/dev/null`;
367 if ($crontab !~ /fex_cleanup/) {
368 open $crontab,">fex.cron" or die "cannot create fex.cron - $!\n";
369 print {$crontab} $crontab,"\n";
370 print {$crontab} " 3 2 * * * exec $FEXHOME/bin/backup\n";
371 print {$crontab} " 3 3 * * * exec $FEXHOME/bin/fex_cleanup\n";
373 system qw'crontab -u fex fex.cron';
376 chownr('fex:root',$FEXHOME,"$FEXHOME/spool/.");
377 chmodr('go-r',"$FEXHOME/lib","$FEXHOME/cgi-bin","$FEXHOME/spool/.");
380 print "Now check configuration file $FEXHOME/lib/fex.ph and run\n";
381 print "$FEXHOME/bin/fac for further configuration and user management.\n";
382 print "(You can do this as user \"fex\")\n";
385 chmodr('go-r',"$FEXHOME/lib","$FEXHOME/cgi-bin");
388 print "F*EX update installed.\n";
389 print "You can inform your users about the new features with:\n";
390 print "$FEXHOME/bin/fexwall 'new F*EX features on $hostname' ".
391 "< $FEXHOME/doc/newfeatures\n";
394 if (@local_rdomains and not @local_rhosts) {
395 print "\nWARNING:\n";
396 print "In $fph you have \@local_rdomains but not \@local_rhosts!\n";
397 print "Selfregistrating of external users will not work!\n";
398 print "See ${fph}_new/\n";
401 if (`$sendmail -h 2>&1 </dev/null` =~ /exim/ and
402 `grep trusted_users /etc/exim4/exim4.conf 2>/dev/null` !~ /\bfex\b/) {
403 print "\nWARNING:\n";
404 print "$sendmail is exim\n";
405 print "You MUST set in your exim4.conf:\n";
406 print "trusted_users = mail : uucp : fex\n";
412 my $ad = dirname($aa);
414 open $aa,'>',$aa or die "$0: cannot create $aa - $!\n";
415 print {$aa} "$admin_pw\n";
417 my $fd = dirname($fid);
419 rename $fid,$fid.'_save';
420 open $fid,'>',$fid or die "$0: cannot create $fid - $!\n";
421 print {$fid} "$hostname:$opt_p\n";
422 print {$fid} "$admin\n";
423 print {$fid} "$admin_pw\n";
425 chownr('fex',$ad,$fd);
433 if (m:^/*(lib|usr|home)?/*$:) {
434 die "ERROR: short path in chownr $user @_\n";
437 system qw'chown -R',$user,@_;
444 if (m:^/*(lib|usr|home)?/*$:) {
445 die "ERROR: short path in chmodr $mod @_\n";
448 system qw'chmod -R',$mod,@_;
452 my ($f,$d,$to,$from,$link);
457 our ($spooldir,$skeydir,$gkeydir);
458 $ENV{FEXLIB} = $FEXLIB = "$FEXHOME/lib";
459 require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n";
460 die "no \$spooldir in $FEXLIB/fex.pp\n" unless $spooldir;
461 die "\$spooldir=$spooldir/" if $spooldir =~ m:^/*(root)?$:;
463 # User --> user@maildomain
465 foreach $f (glob "$spooldir/.dkeys/*") {
466 if ($link = readlink $f) {
467 (undef,$to,$from,$file) = split('/',$link);
469 $to .= '@'.$mdomain if $to !~ /@/;
470 $from .= '@'.$mdomain if $from !~ /@/;
471 if ($link ne "../$to/$from/$file") {
472 symlink "../$to/$from/$file",$f;
479 # fix spool layout: FROM and TO must have domains and must be lower case
480 foreach $d ((glob "$spooldir/*/*"),(glob "$spooldir/*")) {
481 if (not -l $d and -d $d and $d =~ m:(.+)/(.+):) {
484 if ($b !~ /^@/ and $b !~ /^[A-Z_-]+$/) {
485 if ($mdomain and $b !~ /@/) {
486 rename $d,sprintf("%s/%s@%s",$p,lc($b),$mdomain);
487 } elsif ($b ne lc($b)) {
488 rename $d,sprintf("%s/%s",$p,lc($b));
494 # split auth-ID and subuser file: @ --> @ @SUBUSER
495 foreach my $u (glob "$spooldir/*@*") {
496 next if -f "$u/\@SUBUSER";
497 open my $idf,"$u/\@" or next;
499 if (defined ($su = <$idf>) and $su =~ /\w/
500 and open my $suf,">$u/\@SUBUSER") {
502 while (defined ($su = <$idf>)) { print {$suf} $su }
505 if (open my $idf,">$u/\@") {
513 foreach my $sf (glob "$spooldir/*/\@SUBUSER") {
514 $user = (split '/',$sf)[-2];
518 if (/(.+\@.+):(.+)/) {
519 ($subuser,$id) = ($1,$2);
520 next if $subuser =~ /\*/;
521 $skey = md5_hex("$user:$subuser:$id");
522 if (open $skey,'>',"$skeydir/$skey") {
523 print {$skey} "from=$subuser\n",
528 mkdirp("$spooldir/$subuser/\@MAINUSER");
529 symlink $skey,"$spooldir/$subuser/\@MAINUSER/$user";
537 foreach my $gf (glob "$spooldir/*/\@GROUP/*") {
539 # normalize group name
540 if ($gf =~ m:(.+)/(.+):) {
544 $g2 =~ s/[^\w\*%^+=:,.!-]/_/g;
546 rename "$gd/$g1","$gd/$g2" and $gf = "$gd/$g2";
549 $group = (split '/',$gf)[-1];
550 $user = (split '/',$gf)[-3];
554 if (/(.+\@.+):(.+)/) {
556 $gkey = md5_hex("$user:$group:$gm:$id");
557 if (open $gkey,'>',"$gkeydir/$gkey") {
558 print {$gkey} "from=$gm\n",
564 mkdirp("$spooldir/$gm/\@GROUP");
565 symlink "../../$user/\@GROUP/$group","$spooldir/$gm/\@GROUP/$group";
577 die "cpav: $dd is not a directory" unless -d $dd;
578 open P,"tar cf - @_ | su -c 'cd $dd; umask 022; tar xvf - 2>&1' fex |"
579 or die "cpav: cannot tar - $!\n";
582 print "$_ --> $dd/$_\n" unless /\/$/;