Annotation of doc/install/linux/install.pl, revision 1.45.2.24

1.1       raeburn     1: #!/usr/bin/perl
                      2: # The LearningOnline Network 
                      3: # Pre-installation script for LON-CAPA
                      4: #
                      5: # Copyright Michigan State University Board of Trustees
                      6: #
                      7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      8: #
                      9: # LON-CAPA is free software; you can redistribute it and/or modify
                     10: # it under the terms of the GNU General Public License as published by
                     11: # the Free Software Foundation; either version 2 of the License, or
                     12: # (at your option) any later version.
                     13: #
                     14: # LON-CAPA is distributed in the hope that it will be useful,
                     15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: # GNU General Public License for more details.
                     18: #
                     19: # You should have received a copy of the GNU General Public License
                     20: # along with LON-CAPA; if not, write to the Free Software
                     21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     22: #
                     23: # http://www.lon-capa.org/
                     24: #
                     25: 
                     26: use strict;
                     27: use File::Copy;
                     28: use Term::ReadKey;
                     29: use DBI;
1.45.2.11  raeburn    30: use File::Spec;
1.43      raeburn    31: use Cwd();
                     32: use File::Basename();
                     33: use lib File::Basename::dirname(Cwd::abs_path($0));
1.1       raeburn    34: use LCLocalization::localize;
                     35: 
                     36: # ========================================================= The language handle
                     37: 
                     38: my %languages = (
                     39:                   ar => 'Arabic', 
                     40:                   de => 'German',
                     41:                   en => 'English',
                     42:                   es => 'Spanish (Castellan)',
                     43:                   fa => 'Persian',
                     44:                   fr => 'French', 
                     45:                   he => 'Hebrew', 
                     46:                   ja => 'Japanese',
                     47:                   pt => 'Portuguese',
                     48:                   ru => 'Russian',
                     49:                   tr => 'Turkish',
                     50:                   zh => 'Chinese Simplified'
                     51:                ); 
                     52: 
                     53: use vars qw($lh $lang);
                     54: $lang = 'en';
                     55: if (@ARGV > 0) {
                     56:     foreach my $poss (keys(%languages)) {
                     57:         if ($ARGV[0] eq $poss) {
                     58:             $lang = $ARGV[0]; 
                     59:         }
                     60:     }
                     61: }
                     62: 
                     63: &get_language_handle($lang);
                     64: 
                     65: # Check user has root privs
                     66: if (0 != $<) {
                     67:     print &mt('This script must be run as root.')."\n".
                     68:           &mt('Stopping execution.')."\n";
                     69:     exit;
                     70: }
                     71: 
                     72: 
                     73: # Globals: filehandle LOG is global.
                     74: if (!open(LOG,">>loncapa_install.log")) {
                     75:     print &mt('Unable to open log file.')."\n".
                     76:           &mt('Stopping execution.')."\n";
                     77:     exit;
                     78: } else {
1.45.2.24! raeburn    79:     print LOG '$Id: install.pl,v 1.45.2.23 2024/08/05 13:42:44 raeburn Exp $'."\n";
1.1       raeburn    80: }
                     81: 
                     82: #
1.2       raeburn    83: # Helper routines and routines to establish recommended actions
1.1       raeburn    84: #
                     85: 
                     86: sub get_language_handle {
                     87:     my @languages = @_;
                     88:     $lh=LCLocalization::localize->get_handle(@languages);
                     89: }
                     90: 
                     91: sub mt (@) {
                     92:     if ($lh) {
                     93:         if ($_[0] eq '') {
                     94:             if (wantarray) {
                     95:                 return @_;
                     96:             } else {
                     97:                 return $_[0];
                     98:             }
                     99:         } else {
                    100:             return $lh->maketext(@_);
                    101:         }
                    102:     } else {
                    103:         if (wantarray) {
                    104:             return @_;
                    105:         } else {
                    106:             return $_[0];
                    107:         }
                    108:     }
                    109: }
                    110: 
                    111: sub texthash {
                    112:     my (%hash) = @_;
                    113:     foreach (keys(%hash)) {
                    114:         $hash{$_}=&mt($hash{$_});
                    115:     }
                    116:     return %hash;
                    117: }
                    118: 
                    119: 
                    120: sub skip_if_nonempty {
                    121:     my ($string,$error)=@_;
                    122:     return if (! defined($error));
                    123:     chomp($string);chomp($error);
                    124:     if ($string ne '') {
                    125:         print_and_log("$error\n".&mt('Stopping execution.')."\n");
                    126:         return 1;
                    127:     }
                    128:     return;
                    129: }
                    130: 
                    131: sub writelog {
                    132:     while ($_ = shift) {
                    133:         chomp();
                    134:         print LOG "$_\n";
                    135:     }
                    136: }
                    137: 
                    138: sub print_and_log {
                    139:     while ($_=shift) {
                    140:         chomp();
                    141:         print "$_\n";
                    142:         print LOG "$_\n";
                    143:     }
                    144: }
                    145: 
                    146: sub get_user_selection {
                    147:     my ($defaultrun) = @_;
                    148:     my $do_action = 0;
                    149:     my $choice = <STDIN>;
                    150:     chomp($choice);
                    151:     $choice =~ s/(^\s+|\s+$)//g;
                    152:     my $yes = &mt('y');
                    153:     if ($defaultrun) {
                    154:         if (($choice eq '') || ($choice =~ /^\Q$yes\E/i)) {
                    155:             $do_action = 1;
                    156:         }
                    157:     } else {
                    158:         if ($choice =~ /^\Q$yes\E/i) {
                    159:             $do_action = 1;
                    160:         }
                    161:     }
                    162:     return $do_action;
                    163: }
                    164: 
                    165: sub get_distro {
1.45.2.1  raeburn   166:     my ($distro,$gotprereqs,$updatecmd,$packagecmd,$installnow,$unknown);
1.1       raeburn   167:     $packagecmd = '/bin/rpm -q LONCAPA-prerequisites ';
1.45.2.3  raeburn   168:     if (-e '/etc/oracle-release') {
                    169:         open(IN,'</etc/oracle-release');
                    170:         my $versionstring=<IN>;
                    171:         chomp($versionstring);
                    172:         close(IN);
                    173:         if ($versionstring =~ /^Oracle Linux Server release (\d+)/) {
                    174:             my $version = $1;
                    175:             $distro = 'oracle'.$1;
                    176:             $updatecmd = 'yum install LONCAPA-prerequisites';
                    177:             $installnow = 'yum -y install LONCAPA-prerequisites';
                    178:         }
                    179:     } elsif (-e '/etc/redhat-release') {
1.1       raeburn   180:         open(IN,'</etc/redhat-release');
                    181:         my $versionstring=<IN>;
                    182:         chomp($versionstring);
                    183:         close(IN);
                    184:         if ($versionstring =~ /^Red Hat Linux release ([\d\.]+) /) {
                    185:             my $version = $1;
                    186:             if ($version=~/^7\./) {
                    187:                 $distro='redhat7';
                    188:             } elsif ($version=~/^8\./) {
                    189:                 $distro='redhat8';
                    190:             } elsif ($version=~/^9/) {
                    191:                 $distro='redhat9';
                    192:             }
                    193:         } elsif ($versionstring =~ /Fedora( Core)? release ([\d\.]+) /) {
                    194:             my $version=$2;
                    195:             if ($version - int($version) > .9) {
                    196:                 $distro = 'fedora'.(int($version)+1);
                    197:             } else {
                    198:                 $distro = 'fedora'.int($version);
                    199:             }
                    200:             $updatecmd = 'yum install LONCAPA-prerequisites';
                    201:             $installnow = 'yum -y install LONCAPA-prerequisites';
                    202:         } elsif ($versionstring =~ /Red Hat Enterprise Linux [AE]S release ([\d\.]+) /) {
                    203:             $distro = 'rhes'.$1;
                    204:             $updatecmd = 'up2date -i LONCAPA-prerequisites';
                    205:         } elsif ($versionstring =~ /Red Hat Enterprise Linux Server release (\d+)/) {
                    206:             $distro = 'rhes'.$1;
                    207:             $updatecmd = 'yum install LONCAPA-prerequisites';
                    208:             $installnow = 'yum -y install LONCAPA-prerequisites';
1.45.2.3  raeburn   209:         } elsif ($versionstring =~ /Red Hat Enterprise Linux release (\d+)/) {
                    210:             $distro = 'rhes'.$1;
                    211:             $updatecmd = 'dnf install LONCAPA-prerequisites';
                    212:             $installnow = 'dnf -y install LONCAPA-prerequisites';
1.45.2.18  raeburn   213:         } elsif ($versionstring =~ /CentOS(| Linux| Stream) release (\d+)/) {
                    214:             $distro = 'centos'.$2;
                    215:             if ($1 eq ' Stream') {
                    216:                 $distro .= '-stream';
                    217:             }
1.1       raeburn   218:             $updatecmd = 'yum install LONCAPA-prerequisites';
                    219:             $installnow = 'yum -y install LONCAPA-prerequisites';
1.22      raeburn   220:         } elsif ($versionstring =~ /Scientific Linux (?:SL )?release ([\d.]+) /) {
1.1       raeburn   221:             my $ver = $1;
                    222:             $ver =~ s/\.\d+$//;
                    223:             $distro = 'scientific'.$ver;
                    224:             $updatecmd = 'yum install LONCAPA-prerequisites';
                    225:             $installnow = 'yum -y install LONCAPA-prerequisites';
1.45.2.18  raeburn   226:         } elsif ($versionstring =~ /Rocky Linux release ([\d.]+)/) {
                    227:             my $ver = $1;
                    228:             $ver =~ s/\.\d+$//;
                    229:             $distro = 'rocky'.$ver;
                    230:             $updatecmd = 'dnf install LONCAPA-prerequisites';
                    231:             $installnow = 'dnf -y install LONCAPA-prerequisites';
                    232:         } elsif ($versionstring =~ /AlmaLinux release ([\d.]+) /) {
                    233:             my $ver = $1;
                    234:             $ver =~ s/\.\d+$//;
                    235:             $distro = 'alma'.$ver;
                    236:             $updatecmd = 'dnf install LONCAPA-prerequisites';
                    237:             $installnow = 'dnf -y install LONCAPA-prerequisites';
1.1       raeburn   238:         } else {
                    239:             print &mt('Unable to interpret [_1] to determine system type.',
                    240:                       '/etc/redhat-release')."\n";
1.45.2.1  raeburn   241:             $unknown = 1;
1.1       raeburn   242:         }
                    243:     } elsif (-e '/etc/SuSE-release') {
                    244:         open(IN,'</etc/SuSE-release');
                    245:         my $versionstring=<IN>;
                    246:         chomp($versionstring);
                    247:         close(IN);
                    248:         if ($versionstring =~ /^SUSE LINUX Enterprise Server ([\d\.]+) /i) {
                    249:             $distro='sles'.$1;
                    250:             if ($1 >= 10) {
                    251:                 $updatecmd = 'zypper install LONCAPA-prerequisites';
                    252:             } else {
                    253:                 $updatecmd = 'yast -i LONCAPA-prerequisites';
                    254:             }
                    255:         } elsif ($versionstring =~ /^SuSE Linux ([\d\.]+) /i) {
                    256:             $distro = 'suse'.$1;
1.12      raeburn   257:             $updatecmd = 'yast -i LONCAPA-prerequisites';
1.1       raeburn   258:         } elsif ($versionstring =~ /^openSUSE ([\d\.]+) /i) {
                    259:             $distro = 'suse'.$1;
                    260:             if ($1 >= 10.3 ) {
                    261:                 $updatecmd = 'zypper install LONCAPA-prerequisites';
                    262:             } else {
                    263:                 $updatecmd = 'yast -i LONCAPA-prerequisites';
                    264:             }
                    265:         } else {
                    266:             print &mt('Unable to interpret [_1] to determine system type.',
                    267:                       '/etc/SuSE-release')."\n";
1.45.2.1  raeburn   268:             $unknown = 1;
1.1       raeburn   269:         }
                    270:     } elsif (-e '/etc/issue') {
                    271:         open(IN,'</etc/issue');
                    272:         my $versionstring=<IN>;
                    273:         chomp($versionstring);
                    274:         close(IN);
                    275:         if ($versionstring =~ /^Ubuntu (\d+)\.\d+/i) {
                    276:             $distro = 'ubuntu'.$1;
                    277:             $updatecmd = 'sudo apt-get install loncapa-prerequisites';
                    278:         } elsif ($versionstring =~ /^Debian\s+GNU\/Linux\s+(\d+)\.\d+/i) {
                    279:             $distro = 'debian'.$1;
1.45.2.1  raeburn   280:             $updatecmd = 'apt-get install loncapa-prerequisites';
1.1       raeburn   281:         } elsif (-e '/etc/debian_version') {
                    282:             open(IN,'</etc/debian_version');
                    283:             my $version=<IN>;
                    284:             chomp($version);
                    285:             close(IN);
                    286:             if ($version =~ /^(\d+)\.\d+\.?\d*/) {
                    287:                 $distro='debian'.$1;
1.45.2.1  raeburn   288:                 $updatecmd = 'apt-get install loncapa-prerequisites';
1.1       raeburn   289:             } else {
                    290:                 print &mt('Unable to interpret [_1] to determine system type.',
                    291:                           '/etc/debian_version')."\n";
1.45.2.1  raeburn   292:                 $unknown = 1;
1.1       raeburn   293:             }
1.45.2.1  raeburn   294:         }
                    295:         if ($distro ne '') {
                    296:             $packagecmd = '/usr/bin/dpkg -l loncapa-prerequisites ';
1.1       raeburn   297:         }
                    298:     } elsif (-e '/etc/debian_version') {
                    299:         open(IN,'</etc/debian_version');
                    300:         my $version=<IN>;
                    301:         chomp($version);
                    302:         close(IN);
                    303:         if ($version =~  /^(\d+)\.\d+\.?\d*/) {
                    304:             $distro='debian'.$1;
                    305:             $packagecmd = '/usr/bin/dpkg -l loncapa-prerequisites ';
                    306:             $updatecmd = 'apt-get install loncapa-prerequisites';
                    307:         } else {
                    308:             print &mt('Unable to interpret [_1] to determine system type.',
                    309:                       '/etc/debian_version')."\n";
1.45.2.1  raeburn   310:             $unknown = 1;
                    311:         }
                    312:     }
                    313:     if (($distro eq '') && (!$unknown)) {
                    314:         if (-e '/etc/os-release') {
                    315:             if (open(IN,'<','/etc/os-release')) {
                    316:                 my ($id,$version);
                    317:                 while(<IN>) {
                    318:                     chomp();
                    319:                     if (/^ID="(\w+)"/) {
                    320:                         $id=$1;
                    321:                     } elsif (/^VERSION_ID="([\d\.]+)"/) {
                    322:                         $version=$1;
                    323:                     }
                    324:                 }
                    325:                 close(IN);
                    326:                 if ($id eq 'sles') {
                    327:                     my ($major,$minor) = split(/\./,$version);
                    328:                     if ($major =~ /^\d+$/) {
                    329:                         $distro = $id.$major;
                    330:                         $updatecmd = 'zypper install LONCAPA-prerequisites';
                    331:                     }
                    332:                 }
                    333:             }
                    334:             if ($distro eq '') {
                    335:                 print &mt('Unable to interpret [_1] to determine system type.',
                    336:                           '/etc/os-release')."\n";
                    337:                 $unknown = 1;
                    338:             }
                    339:         } else {
1.45.2.3  raeburn   340:             print &mt('Unknown installation: expecting a debian, ubuntu, suse, sles, redhat, fedora, scientific linux, or oracle linux system.')."\n";
1.1       raeburn   341:         }
                    342:     }
                    343:     return ($distro,$packagecmd,$updatecmd,$installnow);
                    344: }
                    345: 
                    346: sub check_prerequisites {
                    347:     my ($packagecmd,$distro) = @_;
                    348:     my $gotprereqs;
                    349:     if ($packagecmd ne '') {
                    350:         if (open(PIPE,"$packagecmd|")) {
                    351:             if ($distro =~ /^(debian|ubuntu)/) {
                    352:                 my @lines = <PIPE>;
                    353:                 chomp(@lines);
                    354:                 foreach my $line (@lines) {
                    355:                     if ($line =~ /^ii\s+loncapa-prerequisites\s+([\w\.]+)/) {
                    356:                         $gotprereqs = $1;
                    357:                     }
                    358:                 }
                    359:             } else {
                    360:                 my $line = <PIPE>;
                    361:                 chomp($line);
1.8       raeburn   362:                 if ($line =~ /^LONCAPA\-prerequisites\-([\d\-]+)\.(?:[.\w]+)$/) {
1.1       raeburn   363:                     $gotprereqs = $1;
                    364:                 }
                    365:             }
                    366:             close(PIPE);
                    367:         } else {
                    368:             print &mt('Error: could not determine if LONCAPA-prerequisites package is installed')."\n";
                    369:         }
                    370:     }
                    371:     return $gotprereqs;
                    372: }
                    373: 
1.6       raeburn   374: sub check_locale {
                    375:     my ($distro) = @_;
1.45.2.22  raeburn   376:     my ($fh,$langvar,$command,$langcmd,$earlyout,$default);
1.8       raeburn   377:     $langvar = 'LANG';
1.6       raeburn   378:     if ($distro =~ /^(ubuntu|debian)/) {
                    379:         if (!open($fh,"</etc/default/locale")) {
                    380:             print &mt('Failed to open: [_1], default locale not checked.',
                    381:                       '/etc/default/locale');
1.45.2.7  raeburn   382:             $earlyout = 1;
1.6       raeburn   383:         }
1.45.2.1  raeburn   384:     } elsif ($distro =~ /^(suse|sles)(\d+)/) {
                    385:         if (($1 eq 'sles') && ($2 >= 15)) {
                    386:             if (!open($fh,"</etc/locale.conf")) {
                    387:                 print &mt('Failed to open: [_1], default locale not checked.',
                    388:                           '/etc/locale.conf');
1.45.2.7  raeburn   389:                 $earlyout = 1;
1.45.2.1  raeburn   390:             }
                    391:         } else {
                    392:             if (!open($fh,"</etc/sysconfig/language")) {
                    393:                 print &mt('Failed to open: [_1], default locale not checked.',
                    394:                           '/etc/sysconfig/language');
1.45.2.7  raeburn   395:                 $earlyout = 1;
1.45.2.1  raeburn   396:             }
                    397:             $langvar = 'RC_LANG';
1.8       raeburn   398:         }
1.24      raeburn   399:     } elsif ($distro =~ /^fedora(\d+)/) {
                    400:         if ($1 >= 18) {
                    401:             if (!open($fh,"</etc/locale.conf")) {
                    402:                 print &mt('Failed to open: [_1], default locale not checked.',
                    403:                           '/etc/locale.conf');
1.45.2.7  raeburn   404:                 $earlyout = 1;
1.24      raeburn   405:             }
                    406:         } elsif (!open($fh,"</etc/sysconfig/i18n")) {
                    407:             print &mt('Failed to open: [_1], default locale not checked.',
                    408:                       '/etc/sysconfig/i18n');
1.45.2.7  raeburn   409:             $earlyout = 1;
1.24      raeburn   410:         }
1.45.2.18  raeburn   411:     } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {
1.29      raeburn   412:         if ($1 >= 7) {
                    413:             if (!open($fh,"</etc/locale.conf")) {
                    414:                 print &mt('Failed to open: [_1], default locale not checked.',
                    415:                           '/etc/locale.conf');
1.45.2.7  raeburn   416:                 $earlyout = 1;
1.29      raeburn   417:             }
                    418:         } elsif (!open($fh,"</etc/sysconfig/i18n")) {
                    419:             print &mt('Failed to open: [_1], default locale not checked.',
                    420:                       '/etc/sysconfig/i18n');
1.45.2.7  raeburn   421:             $earlyout = 1;
1.29      raeburn   422:         }
1.6       raeburn   423:     } else {
                    424:         if (!open($fh,"</etc/sysconfig/i18n")) {
                    425:             print &mt('Failed to open: [_1], default locale not checked.',
                    426:                       '/etc/sysconfig/i18n');
1.45.2.7  raeburn   427:             $earlyout = 1;
1.6       raeburn   428:         }
                    429:     }
1.45.2.22  raeburn   430:     return () if ($earlyout);
1.6       raeburn   431:     my @data = <$fh>;
                    432:     chomp(@data);
1.45.2.22  raeburn   433:     close($fh);
1.6       raeburn   434:     foreach my $item (@data) {
1.25      raeburn   435:         if ($item =~ /^\Q$langvar\E=\"?([^\"]*)\"?/) {
1.45.2.22  raeburn   436:             $default = $1;
1.6       raeburn   437:             if ($default ne 'en_US.UTF-8') {
                    438:                 if ($distro =~ /^debian/) {
1.25      raeburn   439:                     $command = 'locale-gen en_US.UTF-8'."\n".
                    440:                                'update-locale LANG=en_US.UTF-8';
1.6       raeburn   441:                 } elsif ($distro =~ /^ubuntu/) {
1.25      raeburn   442:                     $command = 'sudo locale-gen en_US.UTF-8'."\n".
                    443:                                'sudo update-locale LANG=en_US.UTF-8';
1.7       raeburn   444:                 } elsif ($distro =~ /^(suse|sles)/) {
1.45.2.3  raeburn   445:                     $command = 'yast language';
                    446:                 } elsif (-e '/usr/bin/system-config-language') {
1.6       raeburn   447:                     $command = 'system-config-language';
1.45.2.3  raeburn   448:                 } elsif (-e '/usr/bin/localectl') {
1.45.2.4  raeburn   449:                     $command = '/usr/bin/localectl set-locale LANG=en_US.UTF-8';
1.45.2.3  raeburn   450:                 } else {
                    451:                     $command = 'No standard command found';
1.6       raeburn   452:                 }
                    453:             }
                    454:             last;
                    455:         }
                    456:     }
1.45.2.22  raeburn   457: # Check for locales
                    458:     if ($default ne 'en_US.UTF-8') {
                    459:         my ($has_us_english,$has_other_code,$has_other_lang);
                    460:         if (open(PIPE,"locale -a 2>/dev/null |")) {
                    461:             while (<PIPE>) {
                    462:                 chomp();
                    463:                 next if (/^(C(|\.utf8)|POSIX)$/i);
                    464:                 if (/^en_US\.utf8/i) {
                    465:                     $has_us_english = 1;
                    466:                 } elsif (/^[A-Za-z]{2}_[A-Za-z]{2}/) {
                    467:                     $has_other_code = 1;
                    468:                 } elsif (/^[A-Za-z]{3,}/) {
                    469:                     $has_other_lang = 1;
                    470:                 }
                    471:             }
                    472:             close(PIPE);
                    473:             if (!$has_us_english) {
                    474:                 if ($has_other_code || $has_other_lang) {
                    475:                     if ($distro =~ /^ubuntu/) {
                    476:                         $langcmd = "sudo apt-get install language-pack-en\n";
                    477:                     } elsif ($distro =~ /^debian/) {
                    478:                         $langcmd = "apt-get install language-pack-en\n";
                    479:                     } elsif ($distro =~ /^(suse|sles)/) {
                    480:                         $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n";
                    481:                     } elsif ($distro =~ /^fedora(\d+)$/) {
                    482:                         if ($1 > 23) {
                    483:                             $langcmd = "dnf install glibc-langpack-en\n";
                    484:                         } else {
                    485:                             $langcmd = "yum install glibc-common\n";
                    486:                         }
                    487:                     } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {
                    488:                         if ($1 > 7) {
                    489:                             $langcmd = "dnf install glibc-langpack-en\n";
                    490:                         } else {
                    491:                             $langcmd = "yum install glibc-common\n";
                    492:                         }
                    493:                     }
                    494:                 } else {
                    495:                     if ($distro =~ /^ubuntu/) {
                    496:                         $langcmd = "sudo apt-get install language-pack-en\n";
                    497:                     } elsif ($distro =~ /^debian/) {
                    498:                         $langcmd = "apt-get install language-pack-en\n";
                    499:                     } elsif ($distro =~ /^(suse|sles)/) {
                    500:                         $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n";
                    501:                     } elsif ($distro =~ /^fedora(\d+)$/) {
                    502:                         if ($1 > 23) {
                    503:                             $langcmd = &mt('Either install all languages[_1]or install English only[_2]',
                    504:                                            ":\ndnf install glibc-all-langpacks\n\n",
                    505:                                            ":\ndnf install glibc-langpack-en\n");
                    506:                         } else {
                    507:                             $langcmd = "yum install glibc-common\n";
                    508:                         }
                    509:                     } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {
                    510:                         if ($1 > 7) {
                    511:                             $langcmd = &mt('Either install all languages[_1]or install English only[_2]',
                    512:                                            ":\ndnf install glibc-all-langpacks\n\n",
                    513:                                            ":\ndnf install glibc-langpack-en\n");
                    514:                         } else {
                    515:                             $langcmd = "yum install glibc-common\n";
                    516:                         }
                    517:                     }
                    518:                 }
                    519:             }
                    520:         }
                    521:     }
                    522:     return ($command,$langcmd);
1.6       raeburn   523: }
                    524: 
1.1       raeburn   525: sub check_required {
                    526:     my ($instdir,$dsn) = @_;
                    527:     my ($distro,$packagecmd,$updatecmd,$installnow) = &get_distro();
                    528:     if ($distro eq '') {
                    529:         return;
                    530:     }
                    531:     my $gotprereqs = &check_prerequisites($packagecmd,$distro); 
                    532:     if ($gotprereqs eq '') {
1.45.2.22  raeburn   533:         return ($distro,$gotprereqs,'','',$packagecmd,$updatecmd);
1.6       raeburn   534:     }
1.45.2.22  raeburn   535:     my ($localecmd,$langcmd) = &check_locale($distro);
1.6       raeburn   536:     unless ($localecmd eq '') {
1.45.2.22  raeburn   537:         return ($distro,$gotprereqs,$localecmd,$langcmd);
1.1       raeburn   538:     }
1.45.2.9  raeburn   539:     my ($mysqlon,$mysqlsetup,$mysqlrestart,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,
                    540:         %recommended,$downloadstatus,$filetouse,$production,$testing,$apachefw,
1.45.2.12  raeburn   541:         $tostop,$uses_systemctl,$mysql_has_wwwuser);
1.1       raeburn   542:     my $wwwuid = &uid_of_www();
                    543:     my $wwwgid = getgrnam('www');
                    544:     if (($wwwuid eq '') || ($wwwgid eq '')) {
                    545:         $recommended{'wwwuser'} = 1;
                    546:     }
                    547:     unless( -e "/usr/local/sbin/pwauth") {
                    548:         $recommended{'pwauth'} = 1;
                    549:     }
                    550:     $mysqlon = &check_mysql_running($distro);
                    551:     if ($mysqlon) {
1.45.2.14  raeburn   552:         ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket) =
1.45.2.12  raeburn   553:             &check_mysql_setup($instdir,$dsn,$distro);
1.34      raeburn   554:         if ($mysqlsetup eq 'needsrestart') {
                    555:             $mysqlrestart = '';
                    556:             if ($distro eq 'ubuntu') {
1.45.2.19  raeburn   557:                 $mysqlrestart = 'sudo ';
1.34      raeburn   558:             }
                    559:             $mysqlrestart .= 'service mysql restart';
1.45.2.22  raeburn   560:             return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart);
1.1       raeburn   561:         } else {
1.34      raeburn   562:             if ($mysqlsetup eq 'noroot') {
1.1       raeburn   563:                 $recommended{'mysqlperms'} = 1;
1.34      raeburn   564:             } else {
                    565:                 unless ($mysql_has_wwwuser) {
                    566:                     $recommended{'mysqlperms'} = 1;
                    567:                 }
                    568:             }
                    569:             if ($dbh) {
                    570:                 $has_lcdb = &check_loncapa_mysqldb($dbh);
                    571:             }
                    572:             unless ($has_lcdb) {
                    573:                 $recommended{'mysql'} = 1;
1.1       raeburn   574:             }
                    575:         }
                    576:     }
1.5       raeburn   577:     ($recommended{'firewall'},$apachefw) = &chkfirewall($distro);
1.35      raeburn   578:     ($recommended{'runlevels'},$tostop,$uses_systemctl) = &chkconfig($distro,$instdir);
1.45.2.20  raeburn   579:     if ((ref($uses_systemctl) eq 'HASH') && ($uses_systemctl->{'apache'})) {
                    580:         $recommended{'systemd'} = &check_systemd_security($distro);
                    581:     }
1.1       raeburn   582:     $recommended{'apache'} = &chkapache($distro,$instdir);
                    583:     $recommended{'stopsrvcs'} = &chksrvcs($distro,$tostop);
                    584:     ($recommended{'download'},$downloadstatus,$filetouse,$production,$testing) 
1.45.2.16  raeburn   585:         = &need_download($distro,$instdir);
1.45.2.22  raeburn   586:     return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,
1.45.2.9  raeburn   587:             $mysqlrestart,\%recommended,$dbh,$has_pass,$mysql_unix_socket,
                    588:             $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
                    589:             $uses_systemctl);
1.1       raeburn   590: }
                    591: 
                    592: sub check_mysql_running {
                    593:     my ($distro) = @_;
1.23      raeburn   594:     my $use_systemctl;
1.1       raeburn   595:     my $mysqldaemon ='mysqld';
                    596:     if ($distro =~ /^(suse|sles|debian|ubuntu)/) {
                    597:         $mysqldaemon = 'mysql';
                    598:     }
1.6       raeburn   599:     my $process = 'mysqld_safe';
                    600:     my $proc_owner = 'root';
                    601:     if ($distro =~ /^ubuntu(\w+)/) {
                    602:         if ($1 >= 10) {
                    603:             $process = 'mysqld';
                    604:             $proc_owner = 'mysql';
                    605:         }
1.45.2.20  raeburn   606:         if ($1 >= 16) {
                    607:             $use_systemctl = 1;
                    608:         }
1.45.2.19  raeburn   609:     } elsif ($distro =~ /^debian(\w+)/) {
                    610:         if ($1 >= 10) {
                    611:             $process = 'mysql';
                    612:             $proc_owner = 'mysql';
                    613:         }
                    614:         if ($1 >= 11) {
                    615:             $mysqldaemon = 'mariadb';
                    616:         }
1.45.2.20  raeburn   617:         if ($1 >= 9) {
                    618:             $use_systemctl = 1;
                    619:         }
1.35      raeburn   620:     } elsif ($distro =~ /^fedora(\d+)/) {
1.23      raeburn   621:         if ($1 >= 16) {
                    622:             $process = 'mysqld';
                    623:             $proc_owner = 'mysql';
                    624:             $use_systemctl = 1;
                    625:         }
1.39      raeburn   626:         if ($1 >= 19) {
1.37      raeburn   627:             $mysqldaemon ='mariadb';
                    628:         }
1.45.2.17  raeburn   629:         if ($1 >= 34) {
                    630:             $process = 'mariadb';
                    631:         }
1.45.2.18  raeburn   632:     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29      raeburn   633:         if ($1 >= 7) {
                    634:             $mysqldaemon ='mariadb';
                    635:             $process = 'mysqld';
                    636:             $proc_owner = 'mysql';
                    637:             $use_systemctl = 1;
                    638:         }
1.45.2.19  raeburn   639:         if ($1 >= 9) {
                    640:             $process = 'mariadb';
                    641:         }
1.35      raeburn   642:     } elsif ($distro =~ /^sles(\d+)/) {
                    643:         if ($1 >= 12) {
                    644:             $use_systemctl = 1;
1.42      raeburn   645:             $proc_owner = 'mysql';
                    646:             $process = 'mysqld';
1.35      raeburn   647:         }
1.45.2.23  raeburn   648:         if ($1 >= 12) {
1.45.2.1  raeburn   649:             $mysqldaemon ='mariadb';
                    650:         }
1.35      raeburn   651:     } elsif ($distro =~ /^suse(\d+)/) {
                    652:         if ($1 >= 13) {
                    653:             $use_systemctl = 1;
                    654:         }
1.29      raeburn   655:     }
1.35      raeburn   656:     if (open(PIPE,"ps -ef |grep $process |grep ^$proc_owner |grep -v grep 2>&1 |")) {
1.1       raeburn   657:         my $status = <PIPE>;
                    658:         close(PIPE);
                    659:         chomp($status);
1.6       raeburn   660:         if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
1.1       raeburn   661:             print_and_log(&mt('MySQL is running.')."\n");
                    662:             return 1;
                    663:         } else {
1.23      raeburn   664:             if ($use_systemctl) {
                    665:                 system("/bin/systemctl start $mysqldaemon.service >/dev/null 2>&1 ");
                    666:             } else {
                    667:                 system("/etc/init.d/$mysqldaemon start >/dev/null 2>&1 ");
                    668:             }
1.1       raeburn   669:             print_and_log(&mt('Waiting for MySQL to start.')."\n");
                    670:             sleep 5;
1.12      raeburn   671:             if (open(PIPE,"ps -ef |grep $process |grep -v grep 2>&1 |")) {
                    672:                 $status = <PIPE>;
1.1       raeburn   673:                 close(PIPE);
                    674:                 chomp($status);
1.12      raeburn   675:                 if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
1.1       raeburn   676:                     print_and_log(&mt('MySQL is running.')."\n");
                    677:                     return 1;
                    678:                 } else {
1.12      raeburn   679:                     print_and_log(&mt('Still waiting for MySQL to start.')."\n");
                    680:                     sleep 5;
                    681:                     if (open(PIPE,"ps -ef |grep $process |grep -v grep 2>&1 |")) {
                    682:                         $status = <PIPE>;
                    683:                         close(PIPE);
                    684:                         chomp($status);
                    685:                         if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
                    686:                             print_and_log(&mt('MySQL is running.')."\n");
                    687:                             return 1;
                    688:                         } else {
                    689:                             print_and_log(&mt('Given up waiting for MySQL to start.')."\n"); 
                    690:                         }
                    691:                     }
1.1       raeburn   692:                 }
                    693:             }
                    694:         }
                    695:     } else {
                    696:         print &mt('Could not determine if MySQL is running.')."\n";
                    697:     }
                    698:     return;
                    699: }
                    700: 
                    701: sub chkconfig {
1.8       raeburn   702:     my ($distro,$instdir) = @_;
1.23      raeburn   703:     my (%needfix,%tostop,%uses_systemctl);
1.1       raeburn   704:     my $checker_bin = '/sbin/chkconfig';
1.23      raeburn   705:     my $sysctl_bin = '/bin/systemctl';
1.6       raeburn   706:     my %daemon = (
                    707:                   mysql     => 'mysqld',
                    708:                   apache    => 'httpd',
                    709:                   cups      => 'cups',
                    710:                   ntp       => 'ntpd',
                    711:                   memcached => 'memcached',
                    712:     );
1.1       raeburn   713:     my @runlevels = qw/3 4 5/;
                    714:     my @norunlevels = qw/0 1 6/;
                    715:     if ($distro =~ /^(suse|sles)/) {
                    716:         @runlevels = qw/3 5/;
                    717:         @norunlevels = qw/0 2 1 6/;
1.6       raeburn   718:         $daemon{'mysql'} = 'mysql';
                    719:         $daemon{'apache'} = 'apache2';
1.8       raeburn   720:         $daemon{'ntp'}    = 'ntp';
1.1       raeburn   721:         if ($distro =~ /^(suse|sles)9/) {
1.6       raeburn   722:             $daemon{'apache'} = 'apache';
1.1       raeburn   723:         }
1.35      raeburn   724:         if ($distro =~ /^(suse|sles)([\d\.]+)/) {
                    725:             my $name = $1;
                    726:             my $num = $2;
                    727:             if ($num > 11) {
1.26      raeburn   728:                 $uses_systemctl{'apache'} = 1;
1.35      raeburn   729:                 if (($name eq 'sles') || ($name eq 'suse' && $num >= 13.2)) {
                    730:                     $uses_systemctl{'mysql'} = 1;
                    731:                     $uses_systemctl{'ntp'} = 1;
                    732:                     $uses_systemctl{'cups'} = 1;
                    733:                     $uses_systemctl{'memcached'} = 1;
1.45.2.23  raeburn   734:                     if ($name eq 'sles') {
                    735:                         if ($num >= 12) {
                    736:                             $daemon{'mysql'} = 'mariadb';
                    737:                         }
                    738:                         if ($num >= 15) {
                    739:                             $daemon{'ntp'} = 'chronyd';
                    740:                         } else {
                    741:                             $daemon{'ntp'} = 'ntpd';
                    742:                         }
1.45.2.1  raeburn   743:                     } else {
                    744:                         $daemon{'ntp'} = 'ntpd';
                    745:                     }
1.35      raeburn   746:                 }
1.26      raeburn   747:             }
                    748:         }
1.6       raeburn   749:     } elsif ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
                    750:         my $version = $1;
1.1       raeburn   751:         @runlevels = qw/2 3 4 5/;
                    752:         @norunlevels = qw/0 1 6/;
1.44      raeburn   753:         if (($distro =~ /^ubuntu/) && ($version <= 16)) {
                    754:             $checker_bin = '/usr/sbin/sysv-rc-conf';
                    755:         } else {
                    756:             $uses_systemctl{'ntp'} = 1;
                    757:             $uses_systemctl{'mysql'} = 1;
                    758:             $uses_systemctl{'apache'} = 1;
                    759:             $uses_systemctl{'memcached'} = 1;
                    760:             $uses_systemctl{'cups'} = 1;
                    761:         }
1.6       raeburn   762:         $daemon{'mysql'}  = 'mysql';
                    763:         $daemon{'apache'} = 'apache2';
                    764:         $daemon{'ntp'}    = 'ntp';
                    765:         if (($distro =~ /^ubuntu/) && ($version <= 8)) {
                    766:             $daemon{'cups'} = 'cupsys';
                    767:         }
1.45.2.19  raeburn   768:         if ((($distro =~ /^ubuntu/) && ($version >= 18)) ||
                    769:             (($distro  =~ /^debian/) && ($version >= 10))) {
1.45.2.6  raeburn   770:             $daemon{'ntp'}    = 'chrony';
                    771:         }
1.45.2.23  raeburn   772:         if (($distro  =~ /^debian/) && ($version >= 10)) {
1.45.2.19  raeburn   773:             $daemon{'mysql'} = 'mariadb';
                    774:         }
1.26      raeburn   775:     } elsif ($distro =~ /^fedora(\d+)/) {
1.23      raeburn   776:         my $version = $1;
                    777:         if ($version >= 15) {
                    778:             $uses_systemctl{'ntp'} = 1;
                    779:         }
                    780:         if ($version >= 16) {
                    781:             $uses_systemctl{'mysql'} = 1;
                    782:             $uses_systemctl{'apache'} = 1;
1.35      raeburn   783:             $uses_systemctl{'memcached'} = 1;
                    784:             $uses_systemctl{'cups'} = 1;
1.23      raeburn   785:         }
1.39      raeburn   786:         if ($version >= 19) {
1.37      raeburn   787:             $daemon{'mysql'} = 'mariadb';
                    788:         }
1.45.2.5  raeburn   789:         if ($version >= 26) {
                    790:             $daemon{'ntp'} = 'chronyd';
                    791:         }
1.45.2.18  raeburn   792:     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29      raeburn   793:         my $version = $1;
                    794:         if ($version >= 7) {
                    795:             $uses_systemctl{'ntp'} = 1;
                    796:             $uses_systemctl{'mysql'} = 1;
                    797:             $uses_systemctl{'apache'} = 1;
1.35      raeburn   798:             $uses_systemctl{'memcached'} = 1;
                    799:             $uses_systemctl{'cups'} = 1;
1.30      raeburn   800:             $daemon{'mysql'} = 'mariadb';
1.29      raeburn   801:         }
1.45.2.3  raeburn   802:         if (($version >= 8) || ($distro eq 'oracle7')) {
                    803:             $daemon{'ntp'} = 'chronyd';
                    804:         }
1.1       raeburn   805:     }
1.23      raeburn   806:     my $nocheck;
1.1       raeburn   807:     if (! -x $checker_bin) {
1.23      raeburn   808:         if ($uses_systemctl{'mysql'} && $uses_systemctl{'apache'}) {
                    809:             if (! -x $sysctl_bin) {
                    810:                 $nocheck = 1;       
                    811:             }
                    812:         } else {
                    813:             $nocheck = 1;
                    814:         }
                    815:     }
                    816:     if ($nocheck) {
1.6       raeburn   817:         print &mt('Could not check runlevel status for MySQL or Apache')."\n";
1.1       raeburn   818:         return;
                    819:     }
                    820:     my $rlstr = join('',@runlevels);
                    821:     my $nrlstr = join('',@norunlevels);
1.23      raeburn   822: 
1.6       raeburn   823:     foreach my $type ('apache','mysql','ntp','cups','memcached') {
                    824:         my $service = $daemon{$type};
1.23      raeburn   825:         if ($uses_systemctl{$type}) {
1.35      raeburn   826:             if (($type eq 'memcached') || ($type eq 'cups')) {
                    827:                 if (-l "/etc/systemd/system/multi-user.target.wants/$service.service") {
                    828:                     $tostop{$type} = 1;
                    829:                 }
                    830:             } else {
                    831:                 if (!-l "/etc/systemd/system/multi-user.target.wants/$service.service") {
                    832:                     $needfix{$type} = "systemctl enable $service.service";
                    833:                 }
1.23      raeburn   834:             }
                    835:         } else {
                    836:             my $command = $checker_bin.' --list '.$service.' 2>/dev/null';
1.35      raeburn   837:             if ($type eq 'cups') {
1.23      raeburn   838:                 if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
                    839:                     my $version = $1;
                    840:                     if (($distro =~ /^ubuntu/) && ($version <= 8)) {
                    841:                         $command = $checker_bin.' --list cupsys 2>/dev/null';
1.19      raeburn   842:                     }
                    843:                 }
                    844:             }
1.23      raeburn   845:             my $results = `$command`;
                    846:             my $tofix;
                    847:             if ($results eq '') {
                    848:                 if (($type eq 'apache') || ($type eq 'mysql') || ($type eq 'ntp')) {
                    849:                     if ($distro  =~ /^(debian|ubuntu)/) {
                    850:                         $tofix = "update-rc.d $type defaults";
                    851:                     } else {
                    852:                         $tofix = "$checker_bin --add $service\n";
                    853:                     }
1.6       raeburn   854:                 }
1.23      raeburn   855:             } else {
                    856:                 my %curr_runlevels;
                    857:                 for (my $rl=0; $rl<=6; $rl++) {
                    858:                     if ($results =~ /$rl:on/) { $curr_runlevels{$rl}++; }
                    859:                 }
                    860:                 if (($type eq 'apache') || ($type eq 'mysql') || ($type eq 'ntp')) {
                    861:                     my $warning;
                    862:                     foreach my $rl (@runlevels) {
                    863:                         if (!exists($curr_runlevels{$rl})) {
                    864:                             $warning = 1;
                    865:                         }
                    866:                     }
                    867:                     if ($warning) {
                    868:                         $tofix = "$checker_bin --level $rlstr $service on\n";
                    869:                     }
                    870:                 } elsif (keys(%curr_runlevels) > 0) {
                    871:                     $tostop{$type} = 1;
1.1       raeburn   872:                 }
                    873:             }
1.23      raeburn   874:             if ($tofix) {
                    875:                 $needfix{$type} = $tofix;
1.1       raeburn   876:             }
1.5       raeburn   877:         }
1.1       raeburn   878:     }
                    879:     if ($distro =~ /^(suse|sles)([\d\.]+)$/) {
                    880:         my $name = $1;
                    881:         my $version = $2;
                    882:         my ($major,$minor);
                    883:         if ($name eq 'suse') {
                    884:             ($major,$minor) = split(/\./,$version);
                    885:         } else {
                    886:             $major = $version;
                    887:         }
1.45.2.1  raeburn   888:         if (($major > 10) && ($major <= 13)) {
1.8       raeburn   889:             if (&check_SuSEfirewall2_setup($instdir)) {
                    890:                 $needfix{'insserv'} = 1;
                    891:             }
1.1       raeburn   892:         }
                    893:     }
1.35      raeburn   894:     return (\%needfix,\%tostop,\%uses_systemctl);
1.1       raeburn   895: }
                    896: 
1.45.2.20  raeburn   897: sub check_systemd_security {
                    898:     my ($distro) = @_;
                    899:     my $service = 'httpd.service';
                    900:     if ($distro =~ /^(suse|sles|ubuntu|debian)/) {
                    901:         $service = 'apache2.service';
                    902:     }
                    903:     system("systemctl daemon-reload");
1.45.2.24! raeburn   904:     if (open(PIPE,"systemctl show $service --property=ProtectHome --property=RestrictSUIDSGID 2>/dev/null |")) {
        !           905:         my ($protecthome,$suidsgid);
        !           906:         while (my $line = <PIPE>) {
        !           907:             chomp($line);
        !           908:             if ($line =~ /^ProtectHome=(read-only|yes)$/i) {
        !           909:                 $protecthome = 1;
        !           910:             } elsif ($line =~ /^RestrictSUIDSGID=yes$/i) {
        !           911:                 $suidsgid = 1;
        !           912:             }
        !           913:         }
1.45.2.20  raeburn   914:         close(PIPE);
1.45.2.24! raeburn   915:         if ($protecthome) {
        !           916:             return 1;
        !           917:         }
        !           918:         if ($suidsgid) {
1.45.2.20  raeburn   919:             return 1;
                    920:         }
                    921:     } else {
                    922:          print &mt('Could not check systemctl configuration for Apache')."\n";
                    923:     }
                    924:     return 0;
                    925: }
                    926: 
1.45.2.1  raeburn   927: sub uses_firewalld {
                    928:     my ($distro) = @_;
1.45.2.3  raeburn   929:     my ($inuse,$checkfirewalld,$zone);
1.45.2.1  raeburn   930:     if ($distro =~ /^(suse|sles)([\d\.]+)$/) {
                    931:         if (($1 eq 'sles') && ($2 >= 15)) {
                    932:             $checkfirewalld = 1;
                    933:         }
                    934:     } elsif ($distro =~ /^fedora(\d+)$/) {
                    935:         if ($1 >= 18) {
                    936:             $checkfirewalld = 1;
                    937:         }
1.45.2.18  raeburn   938:     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.45.2.1  raeburn   939:         if ($1 >= 7) {
                    940:             $checkfirewalld = 1;
                    941:         }
                    942:     }
                    943:     if ($checkfirewalld) {
                    944:         my ($loaded,$active);
1.45.2.15  raeburn   945:         if (open(PIPE,"systemctl status firewalld 2>/dev/null |")) {
1.45.2.1  raeburn   946:             while (<PIPE>) {
                    947:                 chomp();
                    948:                 if (/^\s*Loaded:\s+(\w+)/) {
                    949:                     $loaded = $1;
                    950:                 }
1.45.2.15  raeburn   951:                 if (/^\s*Active:\s+(\w+)/) {
1.45.2.1  raeburn   952:                     $active = $1;
                    953:                 }
                    954:             }
                    955:             close(PIPE);
                    956:         }
                    957:         if (($loaded eq 'loaded') || ($active eq 'active')) {
                    958:             $inuse = 1;
1.45.2.3  raeburn   959:             my $cmd = 'firewall-cmd --get-default-zone';
                    960:             if (open(PIPE,"$cmd |")) {
                    961:                 my $result = <PIPE>;
                    962:                 chomp($result);
                    963:                 close(PIPE);
                    964:                 if ($result =~ /^\w+$/) {
                    965:                     $zone = $result;
                    966:                 }
                    967:             }
1.45.2.1  raeburn   968:         }
                    969:     }
1.45.2.3  raeburn   970:     return ($inuse,$zone);
1.45.2.1  raeburn   971: }
                    972: 
1.1       raeburn   973: sub chkfirewall {
1.5       raeburn   974:     my ($distro) = @_;
1.1       raeburn   975:     my $configfirewall = 1;
                    976:     my %ports = (
                    977:                     http  =>  80,
                    978:                     https => 443,
                    979:                 );
1.5       raeburn   980:     my %activefw;
1.45.2.3  raeburn   981:     my ($firewalld,$zone) = &uses_firewalld($distro);
                    982:     if ($firewalld) {
                    983:         my %current;
                    984:         if (open(PIPE,'firewall-cmd --permanent --zone='.$zone.' --list-services |')) {
                    985:             my $svc = <PIPE>;
                    986:             close(PIPE);
                    987:             chomp($svc);
                    988:             map { $current{$_} = 1; } (split(/\s+/,$svc));
                    989:         }
                    990:         if ($current{'http'} && $current{'https'}) {
                    991:             $configfirewall = 0;
                    992:         }
                    993:     } else {
                    994:         if (&firewall_is_active()) {
1.45.2.1  raeburn   995:             my $iptables = &get_pathto_iptables();
                    996:             if ($iptables eq '') {
                    997:                 print &mt('Firewall not checked as path to iptables not determined.')."\n";
                    998:             } else {
                    999:                 my @fwchains = &get_fw_chains($iptables,$distro);
                   1000:                 if (@fwchains) {
                   1001:                     foreach my $service ('http','https') {
                   1002:                         foreach my $fwchain (@fwchains) {
                   1003:                             if (&firewall_is_port_open($iptables,$fwchain,$ports{$service})) {
                   1004:                                 $activefw{$service} = 1;
                   1005:                                 last;
                   1006:                             }
1.1       raeburn  1007:                         }
                   1008:                     }
1.45.2.1  raeburn  1009:                     if ($activefw{'http'}) {
                   1010:                         $configfirewall = 0;
                   1011:                     }
                   1012:                 } else {
                   1013:                     print &mt('Firewall not checked as iptables Chains not identified.')."\n";
1.1       raeburn  1014:                 }
                   1015:             }
1.45.2.3  raeburn  1016:         } else {
                   1017:             print &mt('Firewall not enabled.')."\n";
1.1       raeburn  1018:         }
                   1019:     }
1.5       raeburn  1020:     return ($configfirewall,\%activefw);
1.1       raeburn  1021: }
                   1022: 
                   1023: sub chkapache {
                   1024:     my ($distro,$instdir) = @_;
                   1025:     my $fixapache = 1;
1.28      raeburn  1026:     if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
                   1027:         my $distname = $1;
                   1028:         my $version = $2;
1.33      raeburn  1029:         my ($stdconf,$stdsite);
1.45.2.19  raeburn  1030:         if ((($distname eq 'ubuntu') && ($version > 12)) ||
                   1031:             (($distname eq 'debian') && ($version >= 10))) {
1.33      raeburn  1032:             $stdconf = "$instdir/debian-ubuntu/ubuntu14/loncapa_conf";
                   1033:             $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_sites";
                   1034:         } else {
                   1035:             $stdconf = "$instdir/debian-ubuntu/loncapa"; 
                   1036:         }
                   1037:         if (!-e $stdconf) {
1.1       raeburn  1038:             $fixapache = 0;
                   1039:             print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n"; 
1.28      raeburn  1040:         } else {
1.33      raeburn  1041:             my ($configfile,$sitefile);
1.45.2.19  raeburn  1042:             if ((($distname eq 'ubuntu') && ($version > 12)) ||
                   1043:                 (($distname eq 'debian') && ($version >= 10))) {
1.45.2.10  raeburn  1044:                 $sitefile = '/etc/apache2/sites-available/loncapa.conf';
                   1045:                 $configfile = '/etc/apache2/conf-available/loncapa.conf';
1.33      raeburn  1046:             } else {
1.45.2.10  raeburn  1047:                 $configfile = '/etc/apache2/sites-available/loncapa';
1.28      raeburn  1048:             }
1.33      raeburn  1049:             if (($configfile ne '') && (-e $configfile) && (-e $stdconf))  {
                   1050:                 if (open(PIPE, "diff --brief $stdconf $configfile |")) {
1.28      raeburn  1051:                     my $diffres = <PIPE>;
                   1052:                     close(PIPE);
                   1053:                     chomp($diffres);
                   1054:                     unless ($diffres) {
                   1055:                         $fixapache = 0;
                   1056:                     }
1.1       raeburn  1057:                 }
                   1058:             }
1.45.2.19  raeburn  1059:             if ((!$fixapache) && ((($distname eq 'ubuntu') && ($version > 12)) ||
                   1060:                                   (($distname eq 'debian') && ($version >= 10))))  {
1.33      raeburn  1061:                 if (($sitefile ne '') && (-e $sitefile) && (-e $stdsite)) {
                   1062:                     if (open(PIPE, "diff --brief $stdsite $sitefile |")) {
                   1063:                         my $diffres = <PIPE>;
                   1064:                         close(PIPE);
                   1065:                         chomp($diffres);
1.45.2.20  raeburn  1066:                         if ($diffres) {
                   1067:                             $fixapache = 1;
                   1068:                         } else {
1.33      raeburn  1069:                             $fixapache = 0;
                   1070:                         }
                   1071:                     }
                   1072:                 }
                   1073:             }
1.1       raeburn  1074:         }
1.6       raeburn  1075:         if (!$fixapache) {
                   1076:             foreach my $module ('headers.load','expires.load') {
                   1077:                 unless (-l "/etc/apache2/mods-enabled/$module") {
                   1078:                     $fixapache = 1;
                   1079:                 }
                   1080:             }
                   1081:         }
1.45.2.19  raeburn  1082:         if ((!$fixapache) && (($distname eq 'ubuntu') || ($distname eq 'debian'))) {
1.45.2.7  raeburn  1083:             my $sitestatus = "/etc/apache2/mods-available/status.conf";
                   1084:             my $stdstatus = "$instdir/debian-ubuntu/status.conf";
                   1085:             if ((-e $stdstatus) && (-e $sitestatus)) {
                   1086:                 if (open(PIPE, "diff --brief $stdstatus $sitestatus |")) {
                   1087:                     my $diffres = <PIPE>;
                   1088:                     close(PIPE);
                   1089:                     chomp($diffres);
                   1090:                     if ($diffres) {
                   1091:                         $fixapache = 1;
                   1092:                     }
                   1093:                 }
                   1094:             }
                   1095:         }
1.45.2.1  raeburn  1096:     } elsif ($distro =~ /^(suse|sles)([\d\.]+)$/) {
                   1097:         my ($name,$version) = ($1,$2);
1.1       raeburn  1098:         my $apache = 'apache';
1.45.2.1  raeburn  1099:         my $conf_file = "$instdir/sles-suse/default-server.conf";
                   1100:         if ($version >= 10) {
1.8       raeburn  1101:             $apache = 'apache2';
1.1       raeburn  1102:         }
1.45.2.1  raeburn  1103:         if (($name eq 'sles') && ($version >= 12)) {
                   1104:             $conf_file = "$instdir/sles-suse/apache2.4/default-server.conf";
                   1105:         }
                   1106:         if (!-e $conf_file) {
1.1       raeburn  1107:             $fixapache = 0;
                   1108:             print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.45.2.1  raeburn  1109:         } elsif (-e "/etc/$apache/default-server.conf") {
                   1110:             if (open(PIPE, "diff --brief $conf_file /etc/$apache/default-server.conf |")) {
1.9       raeburn  1111:                 my $diffres = <PIPE>;
                   1112:                 close(PIPE);
                   1113:                 chomp($diffres);
                   1114:                 unless ($diffres) {
                   1115:                     $fixapache = 0;
                   1116:                 }
                   1117:             }
                   1118:         }
                   1119:     } elsif ($distro eq 'rhes4') {
                   1120:         if (!-e "$instdir/rhes4/httpd.conf") {
                   1121:             $fixapache = 0;
                   1122:             print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
                   1123:         } elsif ((-e "/etc/httpd/conf/httpd.conf") && (-e "$instdir/rhes4/httpd.conf")) {
                   1124:             if (open(PIPE, "diff --brief $instdir/rhes4/httpd.conf /etc/httpd/conf/httpd.conf |")) {
1.1       raeburn  1125:                 my $diffres = <PIPE>;
                   1126:                 close(PIPE);
                   1127:                 chomp($diffres);
                   1128:                 unless ($diffres) {
                   1129:                     $fixapache = 0;
                   1130:                 }
                   1131:             }
                   1132:         }
                   1133:     } else {
1.14      raeburn  1134:         my $configfile = 'httpd.conf';
1.45.2.5  raeburn  1135:         my $mpmfile = 'mpm.conf';
1.45.2.18  raeburn  1136:         if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29      raeburn  1137:             if ($1 >= 7) {
                   1138:                 $configfile = 'apache2.4/httpd.conf';
                   1139:             } elsif ($1 > 5) {
1.14      raeburn  1140:                 $configfile = 'new/httpd.conf';
                   1141:             }
                   1142:         } elsif ($distro =~ /^fedora(\d+)$/) {
1.29      raeburn  1143:             if ($1 > 17) {
1.45.2.5  raeburn  1144:                 $configfile = 'apache2.4/httpd.conf';
1.29      raeburn  1145:             } elsif ($1 > 10) {
1.15      raeburn  1146:                 $configfile = 'new/httpd.conf';
1.14      raeburn  1147:             }
                   1148:         }
                   1149:         if (!-e "$instdir/centos-rhes-fedora-sl/$configfile") {
1.1       raeburn  1150:             $fixapache = 0;
                   1151:             print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.14      raeburn  1152:         } elsif ((-e "/etc/httpd/conf/httpd.conf") && (-e "$instdir/centos-rhes-fedora-sl/$configfile")) {
                   1153:             if (open(PIPE, "diff --brief $instdir/centos-rhes-fedora-sl/$configfile /etc/httpd/conf/httpd.conf |")) {
1.1       raeburn  1154:                 my $diffres = <PIPE>;
                   1155:                 close(PIPE);
                   1156:                 chomp($diffres);
                   1157:                 unless ($diffres) {
                   1158:                     $fixapache = 0;
                   1159:                 }
                   1160:             }
                   1161:         }
1.45.2.5  raeburn  1162:         if (-e "/etc/httpd/conf.modules.d/00-mpm.conf") {
                   1163:             if (!-e "$instdir/centos-rhes-fedora-sl/$mpmfile") {
                   1164:                 print &mt('Warning: No LON-CAPA Apache MPM configuration file found for installation check.')."\n";
                   1165:             } elsif ((-e "/etc/httpd/conf.modules.d/00-mpm.conf") && (-e "$instdir/centos-rhes-fedora-sl/$mpmfile")) {
                   1166:                 if (open(PIPE, "diff --brief $instdir/centos-rhes-fedora-sl/$mpmfile /etc/httpd/conf.modules.d/00-mpm.conf |")) {
                   1167:                     my $diffres = <PIPE>;
                   1168:                     close(PIPE);
                   1169:                     chomp($diffres);
                   1170:                     if ($diffres) {
                   1171:                         $fixapache = 1;
                   1172:                     }
                   1173:                 }
                   1174:             }
                   1175:         }
1.1       raeburn  1176:     }
                   1177:     return $fixapache;
                   1178: }
                   1179: 
                   1180: sub chksrvcs {
                   1181:     my ($distro,$tostop) = @_;
                   1182:     my %stopsrvcs;
                   1183:     if (ref($tostop) eq 'HASH') {
                   1184:         %stopsrvcs = %{$tostop};
                   1185:     }
1.6       raeburn  1186:     foreach my $service ('cups','memcached') {
1.1       raeburn  1187:         next if (exists($stopsrvcs{$service}));
                   1188:         my $daemon = $service;
                   1189:         if ($service eq 'cups') {
                   1190:             $daemon = 'cupsd';
                   1191:         }
                   1192:         my $cmd = "ps -ef |grep '$daemon' |grep -v grep";
                   1193:         if (open(PIPE,'-|',$cmd)) {
                   1194:             my $daemonrunning = <PIPE>;
                   1195:             chomp($daemonrunning);
                   1196:             close(PIPE);
                   1197:             if ($daemonrunning) {
1.12      raeburn  1198:                 if ($service eq 'memcached') {
1.16      raeburn  1199:                     my $cmd = '/usr/bin/memcached';
                   1200:                     if ($distro =~ /^(suse|sles)/) {
                   1201:                         $cmd = '/usr/sbin/memcached';
                   1202:                     }
1.12      raeburn  1203:                     unless ($daemonrunning =~ m{^www[^/]+\Q$cmd -m 400 -v\E$}) {
1.10      raeburn  1204:                         $stopsrvcs{$service} = 1;
                   1205:                     }
                   1206:                 } else {
                   1207:                     $stopsrvcs{$service} = 1;
                   1208:                 }
1.1       raeburn  1209:             }
                   1210:         }
1.10      raeburn  1211:     }
1.1       raeburn  1212:     return \%stopsrvcs;
                   1213: }
                   1214: 
                   1215: sub need_download {
1.45.2.16  raeburn  1216:     my ($distro,$instdir) = @_;
1.1       raeburn  1217:     my $needs_download = 1;
                   1218:     my ($production,$testing,$stdsizes) = &download_versionslist();
1.45.2.16  raeburn  1219:     my ($localcurrent,$localtesting,%tarball,%localsize,%bymodtime,
1.1       raeburn  1220:         %bysize,$filetouse,$downloadstatus);
1.45.2.16  raeburn  1221:     if (opendir(my $dir,$instdir)) {
1.1       raeburn  1222:         my (@lcdownloads,$version);
                   1223:         foreach my $file (readdir($dir)) {
                   1224:             if ($file =~ /^loncapa\-([\w\-.]+)\.tar\.gz$/) {
                   1225:                 $version = $1;
                   1226:             } else {
                   1227:                 next;
                   1228:             }
                   1229:             if (ref($stdsizes) eq 'HASH') {
                   1230:                 if ($version eq 'current') {
1.45.2.16  raeburn  1231:                     my @stats = stat("$instdir/$file");
1.1       raeburn  1232:                     $localcurrent = $stats[7];
1.4       raeburn  1233:                     if ($localcurrent == $stdsizes->{$production}) {
1.1       raeburn  1234:                         $needs_download = 0;
                   1235:                         $filetouse = $file;
                   1236:                     }
                   1237:                 } elsif ($version eq 'testing') {
1.45.2.16  raeburn  1238:                     my @stats = stat("$instdir/$file");
1.1       raeburn  1239:                     $localtesting = $stats[7];
1.4       raeburn  1240:                     if ($localtesting == $stdsizes->{$testing}) {
1.1       raeburn  1241:                         $needs_download = 0;
                   1242:                         $filetouse = $file;
                   1243:                     }
                   1244:                 }
                   1245:             }
                   1246:             $tarball{$version} = $file;
                   1247:             push(@lcdownloads,$version);
                   1248:         }
                   1249:         if ($needs_download) {
                   1250:             if (@lcdownloads > 0) {
                   1251:                 foreach my $version (@lcdownloads) {
1.45.2.16  raeburn  1252:                     my @stats = stat("$instdir/$tarball{$version}");
1.1       raeburn  1253:                     my $mtime = $stats[9];
                   1254:                     $localsize{$version} = $stats[7];
                   1255:                     if ($mtime) {
                   1256:                         push(@{$bymodtime{$mtime}},$version);
                   1257:                     }
                   1258:                     if ($localsize{$version}) {
                   1259:                         push(@{$bysize{$localsize{$version}}},$version);
                   1260:                     }
                   1261:                 }
                   1262:                 if ($testing) {
                   1263:                     if (exists($localsize{$testing})) {
                   1264:                         if ($stdsizes->{$testing} == $localsize{$testing}) {
                   1265:                             $needs_download = 0;
                   1266:                             $filetouse = 'loncapa-'.$testing.'.tar.gz';
                   1267:                         }
                   1268:                     }
                   1269:                 }
                   1270:                 if ($needs_download) { 
                   1271:                     if ($production) {
                   1272:                         if (exists($localsize{$production})) {
                   1273:                             if ($stdsizes->{$production} == $localsize{$production}) {
                   1274:                                 $needs_download = 0;
                   1275:                                 $filetouse = 'loncapa-'.$production.'.tar.gz';
                   1276:                             }
                   1277:                         }
                   1278:                     }
                   1279:                 }
                   1280:                 if ($needs_download) {
                   1281:                     my @sorted = sort { $b <=> $a } keys(%bymodtime);
                   1282:                     my $newest = $sorted[0];
                   1283:                     if (ref($bymodtime{$newest}) eq 'ARRAY') {
                   1284:                         $downloadstatus = 
1.45.2.16  raeburn  1285:                               "Latest LON-CAPA source download in $instdir is: ".
1.1       raeburn  1286:                               join(',',@{$bymodtime{$newest}})." (downloaded ".
                   1287:                               localtime($newest).")\n";
                   1288:                     }
                   1289:                 } else {
                   1290:                     $downloadstatus = 
1.45.2.16  raeburn  1291:                         "The $instdir directory already contains the latest LON-CAPA version:".
1.1       raeburn  1292:                         "\n".$filetouse."\n"."which can be used for installation.\n";
                   1293:                 }
                   1294:             } else {
1.45.2.16  raeburn  1295:                 $downloadstatus = "The $instdir directory does not appear to contain any downloaded LON-CAPA source code files which can be used for installation.\n";
1.1       raeburn  1296:             }
                   1297:         }
                   1298:     } else {
1.45.2.16  raeburn  1299:         $downloadstatus = "Could not open $instdir directory to look for existing downloads of LON-CAPA source code.\n";
1.1       raeburn  1300:     }
                   1301:     return ($needs_download,$downloadstatus,$filetouse,$production,$testing);
                   1302: }
                   1303: 
                   1304: sub check_mysql_setup {
1.45.2.12  raeburn  1305:     my ($instdir,$dsn,$distro) = @_;
                   1306:     my ($mysqlsetup,$has_pass,$mysql_unix_socket,$mysql_has_wwwuser);
1.1       raeburn  1307:     my $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
1.45.2.19  raeburn  1308:     my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
                   1309:     if (($mysqlname =~ /^MariaDB/i) && (($mysqlversion == 10 && $mysqlminorversion >= 4) || ($mysqlversion >= 11))) {
1.45.2.9  raeburn  1310:         if ($dbh) {
                   1311:             my $sth = $dbh->prepare("SELECT Priv FROM mysql.global_priv WHERE (User = 'root' AND Host ='localhost')");
                   1312:             $sth->execute();
                   1313:             while (my $priv = $sth->fetchrow_array) {
1.45.2.14  raeburn  1314:                 if ($priv =~ /unix_socket/) {
1.45.2.9  raeburn  1315:                     $mysql_unix_socket = 1;
                   1316:                     last;
                   1317:                 }
                   1318:             }
                   1319:             $sth->finish();
                   1320:             if ($mysql_unix_socket) {
                   1321:                 print_and_log(&mt('MariaDB using unix_socket for root access from localhost.')."\n");
                   1322:                 $mysqlsetup = 'rootok';
1.45.2.12  raeburn  1323:                 $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.45.2.9  raeburn  1324:                 return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket);
                   1325:             }
                   1326:         }
                   1327:     }
1.1       raeburn  1328:     if ($dbh) {
1.45.2.12  raeburn  1329:         $mysqlsetup = 'noroot';
1.45.2.19  raeburn  1330:         if (($mysqlname !~ /^MariaDB/i) && (($mysqlversion == 5 && $mysqlminorversion >= 7) || ($mysqlversion >= 6))) {
1.45.2.12  raeburn  1331:             my $sth = $dbh->prepare("SELECT plugin from mysql.user where User='root'");
                   1332:             $sth->execute();
                   1333:             while (my $priv = $sth->fetchrow_array) {
                   1334:                 if ($priv =~ /auth_socket/) {
                   1335:                     $mysql_unix_socket = 1;
                   1336:                     last;
                   1337:                 }
                   1338:             }
                   1339:             $sth->finish();
                   1340:             if ($mysql_unix_socket) {
                   1341:                 print_and_log(&mt('MySQL using unix_socket for root access from localhost.')."\n");
                   1342:                 $mysqlsetup = 'rootok';
                   1343:                 $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
                   1344:                 return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket);
                   1345:             }
1.45.2.14  raeburn  1346:         }
1.1       raeburn  1347:     } elsif ($DBI::err =~ /1045/) {
                   1348:         $has_pass = 1;
1.34      raeburn  1349:     } elsif ($distro =~ /^ubuntu(\d+)$/) {
                   1350:         my $version = $1;
                   1351:         if ($1 > 12) {
                   1352:             print_and_log(&mt('Restarting mysql, please be patient')."\n");
                   1353:             if (open (PIPE, "service mysql restart 2>&1 |")) {
                   1354:                 while (<PIPE>) {
                   1355:                     print $_;
                   1356:                 }
                   1357:                 close(PIPE);
                   1358:             }
                   1359:             $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
                   1360:             if ($dbh) {
                   1361:                 $mysqlsetup = 'noroot';
1.45.2.12  raeburn  1362:                 $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.34      raeburn  1363:             } elsif ($DBI::err =~ /1045/) {
                   1364:                 $has_pass = 1;
                   1365:             } else {
                   1366:                 $mysqlsetup = 'needsrestart';
1.45.2.16  raeburn  1367:                 $mysql_has_wwwuser = &check_mysql_wwwuser();
1.34      raeburn  1368:                 return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser);
                   1369:             }
                   1370:         }
1.1       raeburn  1371:     }
                   1372:     if ($has_pass) {
                   1373:         print &mt('You have already set a root password for the MySQL database.')."\n";
                   1374:         my $currpass = &get_mysql_password(&mt('Please enter the password now'));
                   1375:         $dbh = DBI->connect($dsn,'root',$currpass,{'PrintError'=>0});
                   1376:         if ($dbh) {
                   1377:             $mysqlsetup = 'rootok';
                   1378:             print_and_log(&mt('Password accepted.')."\n");
1.45.2.12  raeburn  1379:             $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.1       raeburn  1380:         } else {
                   1381:             $mysqlsetup = 'rootfail';
                   1382:             print_and_log(&mt('Problem accessing MySQL.')."\n");
                   1383:             if ($DBI::err =~ /1045/) {
                   1384:                 print_and_log(&mt('Perhaps the password was incorrect?')."\n");
                   1385:                 print &mt('Try again?').' ';
                   1386:                 $currpass = &get_mysql_password(&mt('Re-enter password now')); 
                   1387:                 $dbh = DBI->connect($dsn,'root',$currpass,{'PrintError'=>0});
                   1388:                 if ($dbh) {
                   1389:                     $mysqlsetup = 'rootok';
                   1390:                     print_and_log(&mt('Password accepted.')."\n");
1.45.2.12  raeburn  1391:                     $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.1       raeburn  1392:                 } else {
                   1393:                     if ($DBI::err =~ /1045/) {
                   1394:                         print_and_log(&mt('Incorrect password.')."\n");
                   1395:                     }
1.45.2.16  raeburn  1396:                     $mysql_has_wwwuser = &check_mysql_wwwuser();
1.1       raeburn  1397:                 }
                   1398:             }
                   1399:         }
1.34      raeburn  1400:     } elsif ($mysqlsetup ne 'noroot') {
1.1       raeburn  1401:         print_and_log(&mt('Problem accessing MySQL.')."\n");
                   1402:         $mysqlsetup = 'rootfail';
1.45.2.16  raeburn  1403:         $mysql_has_wwwuser = &check_mysql_wwwuser();
1.1       raeburn  1404:     }
1.34      raeburn  1405:     return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser);
1.1       raeburn  1406: }
                   1407: 
                   1408: sub check_mysql_wwwuser {
1.45.2.12  raeburn  1409:     my ($dbh) = @_;
1.1       raeburn  1410:     my $mysql_wwwuser;
1.45.2.12  raeburn  1411:     if ($dbh) {
                   1412:         $mysql_wwwuser = $dbh->selectrow_array("SELECT COUNT(User) FROM mysql.user WHERE (User = 'www' AND Host ='localhost')");
                   1413:     } else {
                   1414:         my $dbhn = DBI->connect("DBI:mysql:database=information_schema",'www','localhostkey',
                   1415:                                 {PrintError => +0}) || return;
                   1416:         if ($dbhn) {
                   1417:             $mysql_wwwuser = 1;
                   1418:             $dbhn->disconnect;
                   1419:         }
1.1       raeburn  1420:     }
                   1421:     return $mysql_wwwuser;
                   1422: }
                   1423: 
                   1424: sub check_loncapa_mysqldb {
                   1425:     my ($dbh) = @_;
                   1426:     my $has_lcdb;
                   1427:     if (ref($dbh)) {
                   1428:         my $sth = $dbh->prepare("SHOW DATABASES");
                   1429:         $sth->execute();
                   1430:         while (my $dbname = $sth->fetchrow_array) {
                   1431:             if ($dbname eq 'loncapa') {
                   1432:                 $has_lcdb = 1;
                   1433:                 last;
                   1434:             }
                   1435:         }
                   1436:         $sth->finish();
                   1437:     }
                   1438:     return $has_lcdb;
                   1439: }
                   1440: 
                   1441: sub get_pathto_iptables {
                   1442:     my $iptables;
                   1443:     if (-e '/sbin/iptables') {
                   1444:         $iptables = '/sbin/iptables';
                   1445:     } elsif (-e '/usr/sbin/iptables') {
                   1446:         $iptables = '/usr/sbin/iptables';
                   1447:     } else {
                   1448:         print &mt('Unable to find iptables command.')."\n";
                   1449:     }
                   1450:     return $iptables;
                   1451: }
                   1452: 
                   1453: sub firewall_is_active {
                   1454:     if (-e '/proc/net/ip_tables_names') {
1.45.2.19  raeburn  1455:         my $status;
1.45.2.1  raeburn  1456:         if (open(PIPE,'cat /proc/net/ip_tables_names |grep filter |')) {
1.45.2.19  raeburn  1457:             $status = <PIPE>;
1.45.2.1  raeburn  1458:             close(PIPE);
                   1459:             chomp($status);
                   1460:             if ($status eq 'filter') {
                   1461:                 return 1;
                   1462:             }
                   1463:         }
1.45.2.19  raeburn  1464:         unless ($status) {
                   1465:             if (open(PIPE,'nft list tables |')) {
                   1466:                 while(<PIPE>) {
                   1467:                     chomp();
                   1468:                     if (/filter$/) {
                   1469:                         $status = 1;
                   1470:                         last;
                   1471:                     }
                   1472:                 }
                   1473:                 close(PIPE);
                   1474:                 if ($status) {
                   1475:                     return 1;
                   1476:                 }
                   1477:             }
                   1478:         }
1.1       raeburn  1479:     }
1.45.2.1  raeburn  1480:     return 0;
1.1       raeburn  1481: }
                   1482: 
                   1483: sub get_fw_chains {
1.5       raeburn  1484:     my ($iptables,$distro) = @_;
1.1       raeburn  1485:     my @fw_chains;
                   1486:     my $suse_config = "/etc/sysconfig/SuSEfirewall2";
                   1487:     my $ubuntu_config = "/etc/ufw/ufw.conf";
                   1488:     if (-e $suse_config) {
                   1489:         push(@fw_chains,'input_ext');
                   1490:     } else {
                   1491:         my @posschains;
                   1492:         if (-e $ubuntu_config) {
                   1493:             @posschains = ('ufw-user-input','INPUT');
1.5       raeburn  1494:         } elsif ($distro =~ /^debian5/) {
                   1495:             @posschains = ('INPUT');
1.45.2.1  raeburn  1496:         } elsif ($distro =~ /^(suse|sles)(\d+)/) {
                   1497:             @posschains = ('IN_public');
1.1       raeburn  1498:         } else {
                   1499:             @posschains = ('RH-Firewall-1-INPUT','INPUT');
                   1500:             if (!-e '/etc/sysconfig/iptables') {
                   1501:                 if (!-e '/var/lib/iptables') {
                   1502:                     print &mt('Unable to find iptables file containing static definitions.')."\n";
                   1503:                 }
                   1504:                 push(@fw_chains,'RH-Firewall-1-INPUT');
                   1505:             }
                   1506:         }
                   1507:         if ($iptables eq '') {
                   1508:             $iptables = &get_pathto_iptables();
                   1509:         }
                   1510:         my %counts;
                   1511:         if (open(PIPE,"$iptables -L -n |")) {
                   1512:             while(<PIPE>) {
                   1513:                 foreach my $chain (@posschains) {
                   1514:                     if (/(\Q$chain\E)/) {
                   1515:                         $counts{$1} ++;
                   1516:                     }
                   1517:                 }
                   1518:             }
                   1519:             close(PIPE);
                   1520:         }
                   1521:         foreach my $fw_chain (@posschains) {
                   1522:             if ($counts{$fw_chain}) {
                   1523:                 unless(grep(/^\Q$fw_chain\E$/,@fw_chains)) {
                   1524:                     push(@fw_chains,$fw_chain);
                   1525:                 }
                   1526:             }
                   1527:         }
                   1528:     }
                   1529:     return @fw_chains;
                   1530: }
                   1531: 
                   1532: sub firewall_is_port_open {
                   1533:     my ($iptables,$fw_chain,$port) = @_;
                   1534:     # returns 1 if the firewall port is open, 0 if not.
                   1535:     #
                   1536:     # check if firewall is active or installed
                   1537:     return if (! &firewall_is_active());
                   1538:     my $count = 0;
                   1539:     if (open(PIPE,"$iptables -L $fw_chain -n |")) {
                   1540:         while(<PIPE>) {
                   1541:             if (/tcp dpt\:\Q$port\E/) {
                   1542:                 $count ++;
                   1543:                 last;
                   1544:             }
                   1545:         }
                   1546:         close(PIPE);
                   1547:     } else {
                   1548:         print &mt('Firewall status not checked: unable to run [_1].','iptables -L')."\n";
                   1549:     }
                   1550:     return $count;
                   1551: }
                   1552: 
                   1553: sub get_mysql_password {
                   1554:     my ($prompt) = @_;
                   1555:     local $| = 1;
                   1556:     print $prompt.': ';
                   1557:     my $newpasswd = '';
                   1558:     ReadMode 'raw';
                   1559:     my $key;
                   1560:     while(ord($key = ReadKey(0)) != 10) {
                   1561:         if(ord($key) == 127 || ord($key) == 8) {
                   1562:             chop($newpasswd);
                   1563:             print "\b \b";
                   1564:         } elsif(!ord($key) < 32) {
                   1565:             $newpasswd .= $key;
                   1566:             print '*';
                   1567:         }
                   1568:     }
                   1569:     ReadMode 'normal';
                   1570:     print "\n";
                   1571:     return $newpasswd;
                   1572: }
                   1573: 
                   1574: sub check_SuSEfirewall2_setup {
                   1575:     my ($instdir) = @_;
                   1576:     my $need_override = 1;
1.9       raeburn  1577:     if ((-e "/etc/insserv/overrides/SuSEfirewall2_setup") && (-e "$instdir/sles-suse/SuSEfirewall2_setup")) {
                   1578:         if (open(PIPE, "diff --brief $instdir/sles-suse/SuSEfirewall2_setup /etc/insserv/overrides/SuSEfirewall2_setup  |")) {
1.1       raeburn  1579:             my $diffres = <PIPE>;
                   1580:             close(PIPE);
                   1581:             chomp($diffres);
                   1582:             unless ($diffres) {
                   1583:                 $need_override = 0;
                   1584:             }
                   1585:         }
                   1586:     }
                   1587:     return $need_override;
                   1588: }
                   1589: 
                   1590: sub download_versionslist {
                   1591:     my ($production,$testing,%sizes);
                   1592:     if (-e "latest.txt") {
                   1593:          unlink("latest.txt");
                   1594:     }
                   1595:     my $rtncode = system("wget http://install.loncapa.org/versions/latest.txt ".
                   1596:                          "> /dev/null 2>&1");
                   1597:     if (!$rtncode) {
                   1598:         if (open(my $fh,"<latest.txt")) {
                   1599:             my @info = <$fh>;
                   1600:             close($fh);
                   1601:             foreach my $line (@info) {
                   1602:                 chomp();
                   1603:                 if ($line =~ /^\QLATEST-IS: \E([\w\-.]+):(\d+)$/) {
                   1604:                      $production = $1;
                   1605:                      $sizes{$1} = $2;
                   1606:                 } elsif ($line =~ /^LATEST-TESTING-IS: \E([\w\-.]+):(\d+)$/) {
                   1607:                      $testing = $1;
                   1608:                      $sizes{$1} = $2;
                   1609:                 }
                   1610:             }
                   1611:         }
                   1612:     }
                   1613:     return ($production,$testing,\%sizes);
                   1614: }
                   1615: 
                   1616: #
                   1617: # End helper routines.
                   1618: # Main script starts here
                   1619: #
                   1620: 
                   1621: print "
                   1622: ********************************************************************
                   1623: 
                   1624:                     ".&mt('Welcome to LON-CAPA')."
                   1625: 
                   1626: ".&mt('This script will configure your system for installation of LON-CAPA.')."
                   1627: 
                   1628: ********************************************************************
                   1629: 
                   1630: ".&mt('The following actions are available:')."
                   1631: 
1.4       raeburn  1632: ".&mt('1.')." ".&mt('Create the www user/group.')."
1.1       raeburn  1633:    ".&mt('This is the user/group ownership under which Apache child processes run.')."
                   1634:    ".&mt('It also owns most directories within the /home/httpd directory.')." 
                   1635:    ".&mt('This directory is where most LON-CAPA files and directories are stored.')."
1.4       raeburn  1636: ".&mt('2.')." ".&mt('Install the package LON-CAPA uses to authenticate users.')."
                   1637: ".&mt('3.')." ".&mt('Set-up the MySQL database.')."
                   1638: ".&mt('4.')." ".&mt('Set-up MySQL permissions.')."
                   1639: ".&mt('5.')." ".&mt('Configure Apache web server.')."
1.45.2.20  raeburn  1640: ".&mt('6.')." ".&mt('Configure systemd security settings for Apache web server.')."
                   1641: ".&mt('7.')." ".&mt('Configure start-up of services.')."
                   1642: ".&mt('8.')." ".&mt('Check firewall settings.')."
                   1643: ".&mt('9.')." ".&mt('Stop services not used by LON-CAPA,')."
1.1       raeburn  1644:    ".&mt('i.e., services for a print server: [_1] daemon.',"'cups'")."
1.45.2.20  raeburn  1645: ".&mt('10.')." ".&mt('Download LON-CAPA source code in readiness for installation.')."
1.1       raeburn  1646: 
                   1647: ".&mt('Typically, you will run this script only once, when you first install LON-CAPA.')." 
                   1648: 
                   1649: ".&mt('The script will analyze your system to determine which actions are recommended.')."
                   1650: ".&mt('The script will then prompt you to choose the actions you would like taken.')."
                   1651: 
                   1652: ".&mt('For each the recommended action will be selected if you hit Enter/Return.')."
                   1653: ".&mt('To override the default, type the lower case option from the two options listed.')."
                   1654: ".&mt('So, if the default is "yes", ~[Y/n~] will be shown -- type n to override.')."
                   1655: ".&mt('Whereas if the default is "no", ~[y/N~] will be shown -- type y to override.')." 
                   1656: 
                   1657: ".&mt('To accept the default, simply hit Enter/Return on your keyboard.')."
                   1658: ".&mt('Otherwise type: y or n then hit the Enter/Return key.')."
                   1659: 
                   1660: ".&mt('Once a choice has been entered for all nine actions, required changes will be made.')."
                   1661: ".&mt('Feedback will be displayed on screen, and also stored in: [_1].','loncapa_install.log')."
                   1662: 
                   1663: ".&mt('Continue? ~[Y/n~] ');
                   1664: 
                   1665: my $go_on = &get_user_selection(1);
                   1666: if (!$go_on) {
                   1667:     exit;
                   1668: }
                   1669: 
                   1670: my $instdir = `pwd`;
                   1671: chomp($instdir);
                   1672: 
                   1673: my %callsub;
1.45.2.20  raeburn  1674: my @actions = ('wwwuser','pwauth','mysql','mysqlperms','apache','systemd',
1.1       raeburn  1675:                'runlevels','firewall','stopsrvcs','download');
                   1676: my %prompts = &texthash( 
                   1677:     wwwuser    => "Create the 'www' user?",
                   1678:     pwauth     => 'Install the package LON-CAPA uses to authenticate users?',
                   1679:     mysql      => 'Set-up the MySQL database?',
                   1680:     mysqlperms => 'Set-up MySQL permissions?',
                   1681:     apache     => 'Configure Apache web server?',
1.45.2.20  raeburn  1682:     systemd    => 'Configure systemd security settings for Apache web server?',
1.1       raeburn  1683:     runlevels  => 'Set overrides for start-up order of services?',
                   1684:     firewall   => 'Configure firewall settings for Apache',
                   1685:     stopsrvcs  => 'Stop extra services not required on a LON-CAPA server?',
                   1686:     download   => 'Download LON-CAPA source code in readiness for installation?',
                   1687: );
                   1688: 
                   1689: print "\n".&mt('Checking system status ...')."\n";
                   1690: 
                   1691: my $dsn = "DBI:mysql:database=mysql";
1.45.2.22  raeburn  1692: my ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart,
1.45.2.9  raeburn  1693:     $recommended,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$downloadstatus,
                   1694:     $filetouse,$production,$testing,$apachefw,$uses_systemctl) = &check_required($instdir,$dsn);
1.1       raeburn  1695: if ($distro eq '') {
                   1696:     print "\n".&mt('Linux distribution could not be verified as a supported distribution.')."\n".
                   1697:           &mt('The following are supported: [_1].',
                   1698:               'CentOS, RedHat Enterprise, Fedora, Scientific Linux, '.
1.45.2.3  raeburn  1699:               'Oracle Linux, openSuSE, SLES, Ubuntu LTS, Debian')."\n\n".
1.1       raeburn  1700:           &mt('Stopping execution.')."\n";
                   1701:     exit;
                   1702: }
1.34      raeburn  1703: if ($mysqlrestart) {
                   1704:     print "\n".&mt('The mysql daemon needs to be restarted using the following command:')."\n".
                   1705:           $mysqlrestart."\n\n".
                   1706:           &mt('Stopping execution of install.pl script.')."\n".
                   1707:           &mt('Please run the install.pl script again, once you have restarted mysql.')."\n";
                   1708:     exit;
                   1709: }
1.6       raeburn  1710: if ($localecmd ne '') {
1.45.2.22  raeburn  1711:     print "\n".&mt('Although the LON-CAPA application itself is localized for a number of different languages,[_1]the default locale language for the Linux OS on which it runs should be US English.',"\n")."\n\n";
                   1712:     if ($langcmd ne '') {
                   1713:         print &mt('Use the following command(s) or action(s) to install a required language package.')."\n\n".
                   1714:               "$langcmd\n";
                   1715:     }
                   1716:     print &mt('Run the following command from the command line to set the default language for your OS,[_1]and then run this LON-CAPA installation set-up script again.',"\n")."\n\n".
1.6       raeburn  1717:     $localecmd."\n\n".
                   1718:     &mt('Stopping execution.')."\n";
                   1719:     exit;
                   1720: }
1.1       raeburn  1721: if (!$gotprereqs) {
1.12      raeburn  1722:     print "\n".&mt('The LONCAPA-prerequisites package is not installed.')."\n".
1.1       raeburn  1723:           &mt('The following command can be used to install the package (and dependencies):')."\n\n".
                   1724:           $updatecmd."\n\n";
                   1725:     if ($installnow eq '') {
                   1726:         print &mt('Stopping execution.')."\n";
                   1727:         exit;
                   1728:     } else {
                   1729:         print &mt('Run command? ~[Y/n~]');
                   1730:         my $install_prereq = &get_user_selection(1);
                   1731:         if ($install_prereq) {
                   1732:             if (open(PIPE,'|-',$installnow)) {
                   1733:                 close(PIPE);
                   1734:                 $gotprereqs = &check_prerequisites($packagecmd,$distro);
                   1735:                 if (!$gotprereqs) {
1.12      raeburn  1736:                     print &mt('The LONCAPA-prerequisites package is not installed.')."\n".
1.1       raeburn  1737:                           &mt('Stopping execution.')."\n";
                   1738:                     exit;
                   1739:                 } else {
1.45.2.22  raeburn  1740:                     ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,
1.45.2.9  raeburn  1741:                      $mysqlrestart,$recommended,$dbh,$has_pass,$mysql_unix_socket,
                   1742:                      $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
                   1743:                      $uses_systemctl) = &check_required($instdir,$dsn);
1.1       raeburn  1744:                 }
                   1745:             } else {
1.12      raeburn  1746:                 print &mt('Failed to run command to install LONCAPA-prerequisites')."\n";
1.1       raeburn  1747:                 exit;
                   1748:             }
                   1749:         } else {
                   1750:             print &mt('Stopping execution.')."\n";
                   1751:             exit;
                   1752:         }
                   1753:     }
                   1754: }
                   1755: unless (ref($recommended) eq 'HASH') {
                   1756:     print "\n".&mt('An error occurred determining which actions are recommended.')."\n\n".
                   1757:           &mt('Stopping execution.')."\n";
                   1758:     exit;
                   1759: }
                   1760: 
                   1761: print "\n";
                   1762: my $num = 0;
                   1763: foreach my $action (@actions) {
                   1764:     $num ++;
                   1765:     my ($yesno,$defaultrun);
                   1766:     if (ref($recommended) eq 'HASH') {
1.4       raeburn  1767:         if (($action eq 'runlevels') || ($action eq 'stopsrvcs')) {
1.1       raeburn  1768:             $yesno = '[y/N]';
                   1769:             if (ref($recommended->{$action}) eq 'HASH') {
                   1770:                 if (keys(%{$recommended->{$action}}) > 0) {
                   1771:                     $yesno = &mt('~[Y/n~]');
                   1772:                     $defaultrun = 1;
                   1773:                 }
                   1774:             }
                   1775:         } else {
                   1776:             if ($action eq 'download') {
                   1777:                 if ($downloadstatus) {
                   1778:                     print "\n$downloadstatus\n";
                   1779:                 }
                   1780:             }
                   1781:             if ($recommended->{$action}) {
                   1782:                 $yesno = mt('~[Y/n~]');
                   1783:                 $defaultrun = 1;
                   1784:             } else {
                   1785:                 $yesno = &mt('~[y/N~]');
                   1786:             }
                   1787:         }
                   1788:         print $num.'. '.$prompts{$action}." $yesno ";
                   1789:         $callsub{$action} = &get_user_selection($defaultrun);
                   1790:     }
                   1791: }
                   1792: 
                   1793: my $lctarball = 'loncapa-current.tar.gz';
                   1794: my $sourcetarball = $lctarball;
                   1795: if ($callsub{'download'}) {
                   1796:     my ($production,$testing,$sizes) = &download_versionslist();
1.45.2.16  raeburn  1797:     my $homedir = '/root';
                   1798:     if ($distro =~ /^ubuntu/) {
                   1799:         if ($instdir ne $homedir) {
                   1800:             ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
                   1801:         }
                   1802:     }
1.1       raeburn  1803:     if ($production && $testing) {
                   1804:         if ($production ne $testing) {
                   1805:             print &mt('Two recent LON-CAPA releases are available: ')."\n".
1.3       raeburn  1806:                   &mt('1.').' '.&mt('A production release - version: [_1].',$production)."\n".
                   1807:                   &mt('2.').' '.&mt('A testing release - version: [_1].',$testing)."\n\n".
1.45.2.16  raeburn  1808:                   &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".
                   1809:                   &mt("Download the production release into $instdir? ~[Y/n~]");
1.1       raeburn  1810:             if (&get_user_selection(1)) {
1.4       raeburn  1811:                 $sourcetarball = 'loncapa-'.$production.'.tar.gz';
1.45.2.16  raeburn  1812:                 print "$sourcetarball will be downloaded into $instdir\n";
1.1       raeburn  1813:             } else {
                   1814:                 print "\n".&mt('Download the testing release? ~[Y/n~]');
                   1815:                 if (&get_user_selection(1)) {
1.4       raeburn  1816:                     $sourcetarball = 'loncapa-'.$testing.'.tar.gz';
1.45.2.16  raeburn  1817:                     print "$sourcetarball will be downloaded into $instdir\n";
                   1818:                 } else {
                   1819:                     $callsub{'download'} = 0;
1.1       raeburn  1820:                 }
                   1821:             }
                   1822:         }
                   1823:     } elsif ($production) {
                   1824:         print &mt('The most recent LON-CAPA release is version: [_1].',$production)."\n".
1.45.2.16  raeburn  1825:               &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".
                   1826:               &mt("Download the production release into $instdir? ~[Y/n~]");
1.1       raeburn  1827:         if (&get_user_selection(1)) {
1.20      raeburn  1828:             $sourcetarball = 'loncapa-'.$production.'.tar.gz';
1.45.2.16  raeburn  1829:             print "$sourcetarball will be downloaded into $instdir\n";
                   1830:         } else {
                   1831:             $callsub{'download'} = 0;
1.1       raeburn  1832:         }
                   1833:     }
                   1834: } elsif ($filetouse ne '') {
                   1835:     $sourcetarball = $filetouse;
                   1836: }
                   1837: 
                   1838: print_and_log("\n");
                   1839: 
                   1840: # Each action: report if skipping, or perform action and provide feedback. 
                   1841: if ($callsub{'wwwuser'}) {
                   1842:     &setup_www();
                   1843: } else {
                   1844:     &print_and_log(&mt('Skipping creation of user [_1].',"'www'")."\n");
                   1845: }
                   1846: 
                   1847: if ($callsub{'pwauth'}) {
1.4       raeburn  1848:     &build_and_install_mod_auth_external($instdir);
1.1       raeburn  1849: } else {
                   1850:     &print_and_log(&mt('Skipping [_1] installation.',"'pwauth'")."\n");
                   1851: }
                   1852: 
                   1853: if ($callsub{'mysql'}) {
                   1854:     if ($dbh) {
1.45.2.9  raeburn  1855:         &setup_mysql($callsub{'mysqlperms'},$dbh,$has_pass,
1.45.2.15  raeburn  1856:                      $mysql_unix_socket,$has_lcdb,$distro);
1.1       raeburn  1857:     } else {
                   1858:         print &mt('Unable to configure MySQL because access is denied.')."\n";
                   1859:     }
                   1860: } else {
                   1861:     &print_and_log(&mt('Skipping configuration of MySQL.')."\n");
                   1862:     if ($callsub{'mysqlperms'}) {
                   1863:         if ($dbh) {
1.45.2.9  raeburn  1864:             &setup_mysql_permissions($dbh,$has_pass,$mysql_unix_socket);
1.1       raeburn  1865:         } else {
                   1866:             print &mt('Unable to configure MySQL because access is denied.')."\n";  
                   1867:         }
                   1868:     } else {
                   1869:         &print_and_log(&mt('Skipping MySQL permissions setup.')."\n");
                   1870:     }
                   1871: }
                   1872: 
                   1873: if ($dbh) {
                   1874:     if (!$dbh->disconnect) {
                   1875:         &print_and_log(&mt('Failed to disconnect from MySQL:')."\n".
                   1876:                        $dbh->errstr);
                   1877:     }
                   1878: }
                   1879: 
                   1880: if ($callsub{'apache'}) {
                   1881:     if ($distro =~ /^(suse|sles)/) {
1.45.2.1  raeburn  1882:         &copy_apache2_suseconf($instdir,$distro);
1.1       raeburn  1883:     } elsif ($distro =~ /^(debian|ubuntu)/) {
1.28      raeburn  1884:         &copy_apache2_debconf($instdir,$distro);
1.1       raeburn  1885:     } else {
1.14      raeburn  1886:         &copy_httpd_conf($instdir,$distro);
1.45.2.5  raeburn  1887:         &copy_mpm_conf($instdir,$distro);
1.1       raeburn  1888:     }
                   1889: } else {
                   1890:     print_and_log(&mt('Skipping configuration of Apache web server.')."\n");
                   1891: }
                   1892: 
1.45.2.20  raeburn  1893: if ($callsub{'systemd'}) {
                   1894:     &check_systemd_update($distro);
                   1895: } else {
                   1896:     print_and_log('Skipping systemd configuration update for web server');
                   1897: }
                   1898: 
1.1       raeburn  1899: if ($callsub{'runlevels'}) {
                   1900:     my $count = 0;
                   1901:     if (ref($recommended) eq 'HASH') {
                   1902:         if (ref($recommended->{'runlevels'}) eq 'HASH') {
                   1903:             foreach my $type (keys(%{$recommended->{'runlevels'}})) {
                   1904:                 next if ($type eq 'insserv');
                   1905:                 $count ++;
                   1906:                 my $command = $recommended->{'runlevels'}{$type};
                   1907:                 if ($command ne '') {
                   1908:                     print_and_log(&mt('Runlevel update command run: [_1].',$command)."\n");
                   1909:                     system($command);
                   1910:                 }
                   1911:             }
                   1912:             if (!$count) {
                   1913:                 print_and_log(&mt('No runlevel updates required.')."\n");
                   1914:             }  
                   1915:         }
                   1916:     }
1.45.2.1  raeburn  1917:     if ($distro =~ /^(suse|sles)(\d+)/) {
                   1918:         unless(($1 eq 'sles') && ($2 >= 15)) {
                   1919:             &update_SuSEfirewall2_setup($instdir);
                   1920:         }
1.11      raeburn  1921:     }
1.1       raeburn  1922: } else {
                   1923:     &print_and_log(&mt('Skipping setting override for start-up order of services.')."\n");
                   1924: }
                   1925: 
                   1926: if ($callsub{'firewall'}) {
1.45.2.3  raeburn  1927:     my ($firewalld,$zone) = &uses_firewalld($distro);
                   1928:     if ($firewalld) {
1.45.2.1  raeburn  1929:         my (%current,%added);
1.45.2.3  raeburn  1930:         if (open(PIPE,"firewall-cmd --permanent --zone=$zone --list-services |")) {
1.45.2.1  raeburn  1931:             my $svc = <PIPE>;
                   1932:             close(PIPE);
                   1933:             chomp($svc);
                   1934:             map { $current{$_} = 1; } (split(/\s+/,$svc));
                   1935:         }
                   1936:         foreach my $service ('http','https') {
                   1937:             unless ($current{$service}) {
1.45.2.3  raeburn  1938:                 if (open(PIPE,"firewall-cmd --permanent --zone=$zone --add-service=$service |")) {
1.45.2.1  raeburn  1939:                     my $result = <PIPE>;
                   1940:                     if ($result =~ /^success/) {
                   1941:                         $added{$service} = 1;
                   1942:                     }
                   1943:                 }
                   1944:             }
                   1945:         }
                   1946:         if (keys(%added) > 0) {
                   1947:             print &mt('Firewall configured to allow access for: [_1].',
                   1948:                       join(', ',sort(keys(%added))))."\n";
1.45.2.13  raeburn  1949:             system('firewall-cmd --reload');
1.45.2.1  raeburn  1950:         }
                   1951:         if ($current{'http'} || $current{'https'}) {
                   1952:             print &mt('Firewall already configured to allow access for:[_1].',
                   1953:                       (($current{'http'})? ' http':'').(($current{'https'})? ' https':''))."\n";
                   1954:         }
                   1955:         unless ($current{'ssh'}) {
1.45.2.13  raeburn  1956:             print &mt('If you would like to allow access to ssh from outside, use the commands:')."\n".
                   1957:                   "firewall-cmd --permanent --zone=$zone --add-service=ssh\n".
                   1958:                   "firewall-cmd --reload\n";
1.45.2.1  raeburn  1959:         }
                   1960:     } elsif ($distro =~ /^(suse|sles)/) {
1.5       raeburn  1961:         print &mt('Use [_1] to configure the firewall to allow access for [_2].',
                   1962:                   'yast -- Security and Users -> Firewall -> Interfaces',
1.45.2.1  raeburn  1963:                   'ssh, http, https')."\n";
1.5       raeburn  1964:     } elsif ($distro =~ /^(debian|ubuntu)(\d+)/) {
                   1965:         if (($1 eq 'ubuntu') || ($2 > 5)) {
                   1966:             print &mt('Use [_1] to configure the firewall to allow access for [_2].',
                   1967:                       'ufw','ssh, http, https')."\n";
                   1968:         } else {
                   1969:             my $fwadded = &get_iptables_rules($distro,$instdir,$apachefw);
                   1970:             if ($fwadded) {
                   1971:                 print &mt('Enable firewall? ~[Y/n~]');
                   1972:                 my $enable_iptables = &get_user_selection(1);
                   1973:                 if ($enable_iptables) {
                   1974:                     system('/etc/network/if-pre-up.d/iptables');
                   1975:                     print &mt('Firewall enabled using rules defined in [_1].',
                   1976:                               '/etc/iptables.loncapa.rules'); 
                   1977:                 }
                   1978:             }
                   1979:         }
1.45.2.3  raeburn  1980:     } elsif ($distro =~ /^(scientific|oracle)/) {
1.11      raeburn  1981:         print &mt('Use [_1] to configure the firewall to allow access for [_2].',
                   1982:                   'system-config-firewall-tui -- Customize',
                   1983:                   'ssh, http')."\n";
1.1       raeburn  1984:     } else {
1.45.2.3  raeburn  1985:         my $version;
1.45.2.18  raeburn  1986:         if ($distro =~ /^(redhat|centos|rocky|alma)(\d+)/) {
1.45.2.3  raeburn  1987:             $version = $1;
                   1988:         }
                   1989:         if ($version > 5) {
                   1990:             print &mt('Use [_1] to configure the firewall to allow access for [_2].',
                   1991:                   'system-config-firewall-tui -- Customize',
                   1992:                   'ssh, http')."\n";
                   1993:         } else {
                   1994:             print &mt('Use [_1] to configure the firewall to allow access for [_2].',
                   1995:                       'setup -- Firewall configuration -> Customize',
                   1996:                       'ssh, http, https')."\n";
                   1997:         }
1.1       raeburn  1998:     }
                   1999: } else {
1.5       raeburn  2000:     &print_and_log(&mt('Skipping Firewall configuration.')."\n");
1.1       raeburn  2001: }
                   2002: 
                   2003: if ($callsub{'stopsrvcs'}) {
1.45      raeburn  2004:     &kill_extra_services($distro,$recommended->{'stopsrvcs'},$uses_systemctl);
1.1       raeburn  2005: } else {
1.10      raeburn  2006:     &print_and_log(&mt('Skipping stopping unnecessary service ([_1] daemons).',"'cups','memcached'")."\n");
1.1       raeburn  2007: }
                   2008: 
                   2009: my ($have_tarball,$updateshown);
                   2010: if ($callsub{'download'}) {
                   2011:     ($have_tarball,$updateshown) = &download_loncapa($instdir,$sourcetarball);
                   2012: } else {
                   2013:     print_and_log(&mt('Skipping download of LON-CAPA tar file.')."\n\n");
                   2014:     print &mt('LON-CAPA is available for download from: [_1]',
                   2015:               'http://install.loncapa.org/')."\n";
                   2016:     if (!-e '/etc/loncapa-release') {
1.45.2.19  raeburn  2017:         &print_and_log(&mt('LON-CAPA is not yet installed on your system.')."\n\n");
                   2018:         unless ($filetouse) {
                   2019:             &print_and_log(&mt('You may retrieve the source for LON-CAPA by executing:')."\n".
                   2020:                            "wget http://install.loncapa.org/versions/$lctarball\n");
                   2021:         }
1.1       raeburn  2022:     } else {
                   2023:         my $currentversion;
                   2024:         if (open(my $fh,"</etc/loncapa-release")) {
                   2025:             my $version = <$fh>;
                   2026:             chomp($version);
                   2027:             if ($version =~ /^\QLON-CAPA release \E([\w\-.]+)$/) {
                   2028:                 $currentversion = $1;
                   2029:             }
                   2030:         }
                   2031:         if ($currentversion ne '') {
                   2032:             print &mt('Version of LON-CAPA currently installed on this server is: [_1].',
                   2033:                       $currentversion),"\n";
                   2034:             if ($production) {
                   2035:                 print &mt('The latest production release of LON-CAPA is [_1].',$production)."\n";
                   2036:             }
                   2037:             if ($testing) {
                   2038:                 print &mt('The latest testing release of LON-CAPA is [_1].',$testing)."\n";
                   2039:             }
                   2040:         }
                   2041:     }
                   2042:     if ($filetouse ne '') {
                   2043:         $have_tarball = 1;
                   2044:     }
                   2045: }
                   2046: 
                   2047: print "\n".&mt('Requested configuration complete.')."\n\n";
                   2048: if ($have_tarball && !$updateshown) {
                   2049:     my ($lcdir) = ($sourcetarball =~ /^([\w.\-]+)\.tar.gz$/);
1.45.2.16  raeburn  2050:     if ($lcdir eq 'loncapa-current') {
                   2051:         $lcdir = "loncapa-X.Y.Z (X.Y.Z should correspond to a version number like '2.11.3')";
                   2052:     }
1.45.2.14  raeburn  2053:     my ($apachename,$lc_uses_systemctl,$uses_sudo);
1.45.2.12  raeburn  2054:     if ($distro =~ /^(suse|sles|debian|ubuntu)([\d.]+)/) {
                   2055:         if (($1 eq 'suse') && ($2 < 10)) {
                   2056:             $apachename = 'apache';
                   2057:         } else {
                   2058:             $apachename = 'apache2';
                   2059:         }
                   2060:     } else {
                   2061:         $apachename = 'httpd';
                   2062:     }
                   2063:     if ($distro =~ /^oracle(\d+)$/) {
                   2064:         if ($1 > 6) {
                   2065:             $lc_uses_systemctl = 1;
                   2066:         }
1.45.2.18  raeburn  2067:     } elsif ($distro =~ /^(?:rhes|centos|rocky|alma)(\d+)/) {
1.45.2.12  raeburn  2068:         if ($1 > 7) {
                   2069:             $lc_uses_systemctl = 1;
                   2070:         }
                   2071:     } elsif ($distro =~ /^ubuntu(\d+)$/) {
                   2072:         if ($1 > 16) {
                   2073:             $lc_uses_systemctl = 1;
                   2074:         }
                   2075:         $uses_sudo = 1;
1.45.2.19  raeburn  2076:     } elsif ($distro =~ /^debian(\d+)$/) {
                   2077:         if ($1 >= 10) {
                   2078:             $lc_uses_systemctl = 1;
                   2079:         }
1.45.2.12  raeburn  2080:     } elsif ($distro =~ /^sles(\d+)$/) {
                   2081:         if ($1 > 12) {
                   2082:             $lc_uses_systemctl = 1;
                   2083:         }
1.45.2.20  raeburn  2084:     } elsif ($distro =~ /^fedora(\d+)$/) {
                   2085:         if ($1 > 25) {
                   2086:             $lc_uses_systemctl = 1;
                   2087:         }
1.45.2.12  raeburn  2088:     }
1.1       raeburn  2089:     if (!-e '/etc/loncapa-release') {
                   2090:         print &mt('If you are now ready to install LON-CAPA, enter the following commands:')."\n\n";
                   2091:     } else {
1.45.2.12  raeburn  2092:         my $lcstop = '/etc/init.d/loncontrol stop';
                   2093:         if ($lc_uses_systemctl) {
                   2094:             $lcstop = 'systemctl stop loncontrol';
                   2095:         }
                   2096:         my $apachestop = "/etc/init.d/$apachename stop";
                   2097:         if ($uses_systemctl) {
                   2098:             $apachestop = "systemctl stop $apachename";
                   2099:         }
                   2100:         if ($uses_sudo) {
1.45.2.16  raeburn  2101:             $lcstop = 'sudo '.$lcstop;
1.45.2.12  raeburn  2102:             $apachestop = 'sudo '.$apachestop;
1.1       raeburn  2103:         }
1.45.2.12  raeburn  2104:         print &mt('If you are now ready to update LON-CAPA, enter the following commands:').
                   2105:               "\n\n$lcstop\n$apachestop\n";
1.1       raeburn  2106:     }
1.45.2.16  raeburn  2107:     my ($extract,$update);
                   2108:     my $homedir = '/root';
                   2109:     if ($uses_sudo) {
                   2110:         $extract = 'sudo ';
                   2111:         $update = 'sudo ';
                   2112:         if ($instdir ne $homedir) {
                   2113:             ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
                   2114:         }
                   2115:     }
                   2116:     $extract .= "tar zxf $sourcetarball --directory $homedir";
                   2117:     $update .= './UPDATE';
                   2118:     print "$extract\n".
                   2119:           "cd $homedir/$lcdir\n".
                   2120:           "$update\n";
1.1       raeburn  2121:     if (-e '/etc/loncapa-release') {
1.45.2.19  raeburn  2122:         my $lcstart = '/etc/init.d/loncontrol start';
1.45.2.12  raeburn  2123:         if ($lc_uses_systemctl) {
                   2124:             $lcstart = '/home/httpd/perl/loncontrol start';
                   2125:         }
                   2126:         my $apachestart = "/etc/init.d/$apachename start";
                   2127:         if ($uses_systemctl) {
                   2128:             $apachestart = "systemctl start $apachename";
                   2129:         }
                   2130:         if ($uses_sudo) {
                   2131:             $lcstart = 'sudo '.$lcstart;
                   2132:             $apachestart = 'sudo '.$apachestart;
                   2133:         }
                   2134:         print "$lcstart\n";
                   2135:         print "$apachestart\n";
1.1       raeburn  2136:     }
                   2137: }
                   2138: exit;
                   2139: 
                   2140: #
                   2141: # End main script
                   2142: #
                   2143: 
                   2144: #
                   2145: # Routines for the actions
                   2146: #
                   2147:  
                   2148: sub setup_www {
                   2149:     ##
                   2150:     ## Set up www
                   2151:     ##
                   2152:     print_and_log(&mt('Creating user [_1]',"'www'")."\n");
                   2153:     # -- Add group
                   2154: 
                   2155:     my $status = `/usr/sbin/groupadd www`;
                   2156:     if ($status =~ /\QGroup `www' already exists.\E/) {
                   2157:         print &mt('Group [_1] already exists.',"'www'")."\n";
                   2158:     } elsif ($status ne '') {
                   2159:         print &mt('Unable to add group [_1].',"'www'")."\n";
                   2160:     }
                   2161:    
                   2162:     my $gid = getgrnam('www');
                   2163: 
                   2164:     if (open (PIPE, "/usr/sbin/useradd -c LONCAPA -g $gid www 2>&1 |")) {
                   2165:         $status = <PIPE>;
                   2166:         close(PIPE);
                   2167:         chomp($status);
                   2168:         if ($status =~ /\QAccount `www' already exists.\E/) {
                   2169:             print &mt('Account [_1] already exists.',"'www'")."\n";
                   2170:         } elsif ($status ne '') {
                   2171:             print &mt('Unable to add user [_1].',"'www'")."\n";
                   2172:         }
                   2173:     }  else {
                   2174:         print &mt('Unable to run command to add user [_1].',"'www'")."\n";
                   2175:     }
                   2176: 
                   2177:     my $uid = &uid_of_www();
                   2178:     if (($gid ne '') && ($uid ne '')) {
                   2179:         if (!-e '/home/www') {
                   2180:             mkdir('/home/www',0755);
                   2181:             system('chown www:www /home/www');
                   2182:         }
                   2183:     }
                   2184:     writelog ($status);
                   2185: }
                   2186: 
                   2187: sub uid_of_www {
                   2188:     my ($num) = (getpwnam('www'))[2];
                   2189:     return $num;
                   2190: }
                   2191: 
                   2192: sub build_and_install_mod_auth_external {
                   2193:     my ($instdir) = @_;
                   2194:     my $num = &uid_of_www();
                   2195:     # Patch pwauth
                   2196:     print_and_log(&mt('Building authentication system for LON-CAPA users.')."\n");
                   2197:     my $patch = <<"ENDPATCH";
                   2198: 148c148
                   2199: < #define SERVER_UIDS 99		/* user "nobody" */
                   2200: ---
                   2201: > #define SERVER_UIDS $num		/* user "www" */
                   2202: ENDPATCH
                   2203: 
1.45.2.19  raeburn  2204:     my $patch_code = <<"ENDPATCH";
                   2205: 127a128
                   2206: > #include <string.h>
                   2207: 214a216
                   2208: > #include <time.h>
                   2209: 566c568
                   2210: < check_fails()
                   2211: ---
                   2212: > int check_fails()
                   2213: 589c591
                   2214: < log_failure()
                   2215: ---
                   2216: > void log_failure()
                   2217: 629c631
                   2218: < snooze(int seconds)
                   2219: ---
                   2220: > void snooze(int seconds)
                   2221: 653c655
                   2222: < main(int argc, char **argv)
                   2223: ---
                   2224: > int main(int argc, char **argv)
                   2225: ENDPATCH
                   2226: 
1.1       raeburn  2227:     if (! -e "/usr/bin/patch") {
                   2228: 	print_and_log(&mt('You must install the software development tools package: [_1], when installing Linux.',"'patch'")."\n");
                   2229:         print_and_log(&mt('Authentication installation not completed.')."\n");
                   2230:         return;
                   2231:     }
                   2232:     if (&skip_if_nonempty(`cd /tmp; tar zxf $instdir/pwauth-2.2.8.tar.gz`,
                   2233: 		     &mt('Unable to extract pwauth')."\n")) {
                   2234:         return;
                   2235:     }
                   2236:     my $dir = "/tmp/pwauth-2.2.8";
1.45.2.19  raeburn  2237:     my $patchedok;
1.1       raeburn  2238:     if (open(PATCH,"| patch $dir/config.h")) {
                   2239:         print PATCH $patch;
                   2240:         close(PATCH);
1.45.2.19  raeburn  2241:         if (open(PATCH,"| patch $dir/pwauth.c")) {
                   2242:             print PATCH $patch_code;
                   2243:             close(PATCH);
                   2244:             $patchedok = 1;
                   2245:         }
                   2246:     }
                   2247:     if ($patchedok) {
1.1       raeburn  2248:         print_and_log("\n");
                   2249:         ##
                   2250:         ## Compile patched pwauth
                   2251:         ##
                   2252:         print_and_log(&mt('Compiling pwauth')."\n");
1.12      raeburn  2253:         my $result = `cd $dir/; make 2>/dev/null `;
1.1       raeburn  2254:         my $expected = <<"END";
                   2255: gcc -g    -c -o pwauth.o pwauth.c
                   2256: gcc -o pwauth -g  pwauth.o -lcrypt
                   2257: END
                   2258:         if ($result eq $expected) {
                   2259:             print_and_log(&mt('Apparent success compiling pwauth:').
                   2260:                           "\n".$result );
                   2261:             # Install patched pwauth
                   2262:             print_and_log(&mt('Copying pwauth to [_1]',' /usr/local/sbin')."\n");
                   2263:             if (copy "$dir/pwauth","/usr/local/sbin/pwauth") {
1.5       raeburn  2264:                 if (chmod(06755, "/usr/local/sbin/pwauth")) {
1.1       raeburn  2265:                     print_and_log(&mt('[_1] copied successfully',"'pwauth'").
                   2266:                                   "\n");
                   2267:                 } else {
                   2268:                     print &mt('Unable to set permissions on [_1].'.
                   2269:                               "/usr/local/sbin/pwauth")."\n";
                   2270:                 }
                   2271:             } else {
                   2272:                 print &mt('Unable to copy [_1] to [_2]',
                   2273:                           "'$dir/pwauth'","/usr/local/sbin/pwauth")."\n$!\n";
                   2274:             }
                   2275:         } else {
                   2276:             print &mt('Unable to compile patched [_1].'."'pwauth'")."\n";
                   2277:         }
                   2278:     } else {
                   2279:         print &mt('Unable to start patch for [_1]',"'pwauth'")."\n";
                   2280:     }
                   2281:     print_and_log("\n");
                   2282: }
                   2283: 
                   2284: sub kill_extra_services {
1.45      raeburn  2285:     my ($distro,$stopsrvcs,$uses_systemctl) = @_;
1.1       raeburn  2286:     if (ref($stopsrvcs) eq 'HASH') {
                   2287:         my @stopping = sort(keys(%{$stopsrvcs}));
                   2288:         if (@stopping) {
1.6       raeburn  2289:             my $kill_list = join("', '",@stopping);
1.1       raeburn  2290:             if ($kill_list) {
                   2291:                 $kill_list = "'".$kill_list."'";
1.6       raeburn  2292:                 &print_and_log("\n".&mt('Killing unnecessary services ([_1] daemon(s)).',$kill_list)."\n");
                   2293:                 foreach my $service (@stopping) {
                   2294:                     my $daemon = $service;
                   2295:                     if ($service eq 'cups') {
                   2296:                         $daemon = 'cupsd';
                   2297:                         if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
                   2298:                             my $version = $1;
                   2299:                             if (($distro =~ /^ubuntu/) && ($version <= 8)) {
                   2300:                                 $daemon = 'cupsys';
                   2301:                             }
1.12      raeburn  2302:                         } else {
1.8       raeburn  2303:                             $daemon = 'cups';
1.6       raeburn  2304:                         }
                   2305:                     }
1.12      raeburn  2306:                     my $cmd = "ps -ef |grep '$daemon' |grep -v grep";
                   2307:                     if (open(PIPE,'-|',$cmd)) {
                   2308:                         my $daemonrunning = <PIPE>;
                   2309:                         chomp($daemonrunning);
                   2310:                         close(PIPE);
                   2311:                         if ($daemonrunning) {
                   2312:                             &print_and_log(`/etc/init.d/$daemon stop`);
                   2313:                         }
                   2314:                     }
1.1       raeburn  2315: 	            &print_and_log(&mt('Removing [_1] from startup.',$service)."\n");
1.45      raeburn  2316:                     if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
                   2317:                         my $version = $1;
1.45.2.19  raeburn  2318:                         if ((($distro =~ /^ubuntu/) && ($version > 16)) ||
                   2319:                             (($distro =~ /^debian/) && ($version >= 10))) {
1.45      raeburn  2320:                             if (ref($uses_systemctl) eq 'HASH') {
                   2321:                                 if ($uses_systemctl->{$service}) {
                   2322:                                     if (`systemctl is-enabled $service`) {
                   2323:                                         &print_and_log(`systemctl disable $service`);
                   2324:                                     }
                   2325:                                 }
                   2326:                             }
                   2327:                         } else {
                   2328:                             &print_and_log(`update-rc.d -f $daemon remove`);
                   2329:                         }
1.1       raeburn  2330:                     } else {
1.35      raeburn  2331:                         if (ref($uses_systemctl) eq 'HASH') {
                   2332:                             if ($uses_systemctl->{$service}) {
                   2333:                                 if (`systemctl is-enabled $service`) {                          
                   2334:                                     &print_and_log(`systemctl disable $service`);
                   2335:                                 }
                   2336:                             } else {
                   2337:                                 &print_and_log(`/sbin/chkconfig --del $service`);
                   2338:                             }
                   2339:                         } else {
                   2340: 	                    &print_and_log(`/sbin/chkconfig --del $service`);
                   2341:                         } 
1.1       raeburn  2342:                     }
                   2343:                 }
                   2344:             }
                   2345:         }
                   2346:     }
                   2347:     return;
                   2348: }
                   2349: 
                   2350: sub setup_mysql {
1.45.2.15  raeburn  2351:     my ($setup_mysql_permissions,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$distro) = @_;
1.4       raeburn  2352:     my @mysql_lc_commands;
1.1       raeburn  2353:     unless ($has_lcdb) {
1.45.2.15  raeburn  2354:         my $createcmd = 'CREATE DATABASE loncapa';
                   2355:         if ($distro =~ /^sles(\d+)/) {
                   2356:             if ($1 > 11) {
                   2357:                 $createcmd .= ' CHARACTER SET utf8 COLLATE utf8_general_ci';
                   2358:             }
                   2359:         } elsif ($distro =~ /^ubuntu(\d+)/) {
                   2360:             if ($1 > 16) {
                   2361:                 $createcmd .= ' CHARACTER SET latin1 COLLATE latin1_swedish_ci';
                   2362:             }
                   2363:         }
                   2364:         push(@mysql_lc_commands,$createcmd);
1.1       raeburn  2365:     }
1.4       raeburn  2366:     push(@mysql_lc_commands,"USE loncapa");
                   2367:     push(@mysql_lc_commands,qq{
1.18      raeburn  2368: CREATE TABLE IF NOT EXISTS metadata (title TEXT, author TEXT, subject TEXT, url TEXT, keywords TEXT, version TEXT, notes TEXT, abstract TEXT, mime TEXT, language TEXT, creationdate DATETIME, lastrevisiondate DATETIME, owner TEXT, copyright TEXT, domain TEXT, dependencies TEXT, modifyinguser TEXT, authorspace TEXT, lowestgradelevel TEXT, highestgradelevel TEXT, standards TEXT, count INT, course INT, course_list TEXT, goto INT, goto_list TEXT, comefrom INT, comefrom_list TEXT, sequsage INT, sequsage_list TEXT, stdno INT, stdno_list TEXT, avetries FLOAT, avetries_list TEXT, difficulty FLOAT, difficulty_list TEXT, disc FLOAT, disc_list TEXT, clear FLOAT, technical FLOAT, correct FLOAT, helpful FLOAT, depth FLOAT, hostname TEXT, FULLTEXT idx_title (title), FULLTEXT idx_author (author), FULLTEXT idx_subject (subject), FULLTEXT idx_url (url), FULLTEXT idx_keywords (keywords), FULLTEXT idx_version (version), FULLTEXT idx_notes (notes), FULLTEXT idx_abstract (abstract), FULLTEXT idx_mime (mime), FULLTEXT idx_language (language), FULLTEXT idx_owner (owner), FULLTEXT idx_copyright (copyright)) ENGINE=MYISAM
1.4       raeburn  2369: });
1.1       raeburn  2370:     if ($setup_mysql_permissions) {
1.45.2.9  raeburn  2371:         &setup_mysql_permissions($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands);
1.1       raeburn  2372:     } else {
                   2373:         print_and_log(&mt('Skipping MySQL permissions setup.')."\n");
                   2374:         if ($dbh) {
1.4       raeburn  2375:             if (@mysql_lc_commands) {
                   2376:                 foreach my $lccmd (@mysql_lc_commands) { 
                   2377:                     $dbh->do($lccmd) || print $dbh->errstr."\n";
                   2378:                 }
                   2379:             }
1.1       raeburn  2380:             print_and_log(&mt('MySQL database set up complete.')."\n");
                   2381:         } else {
                   2382:             print_and_log(&mt('Problem accessing MySQL.')."\n");
                   2383:         }
                   2384:     }
                   2385: }
                   2386: 
                   2387: sub setup_mysql_permissions {
1.45.2.9  raeburn  2388:     my ($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands) = @_;
1.45.2.19  raeburn  2389:     my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
1.45.2.9  raeburn  2390:     my ($usescreate,$usesauth,$is_mariadb,$hasauthcol,@mysql_commands);
1.38      raeburn  2391:     if ($mysqlname =~ /^MariaDB/i) {
1.45.2.2  raeburn  2392:         $is_mariadb = 1;
1.45.2.19  raeburn  2393:         if ((($mysqlversion == 10) && ($mysqlminorversion >= 4)) || ($mysqlversion >= 11)) {
1.45.2.9  raeburn  2394:             $usescreate = 1;
1.45.2.19  raeburn  2395:         } elsif (($mysqlversion == 10) && ($mysqlminorversion >= 2)) {
1.38      raeburn  2396:             $usesauth = 1;
1.45.2.19  raeburn  2397:         } elsif (($mysqlversion == 5) && ($mysqlminorversion >= 5)) {
1.42      raeburn  2398:             $hasauthcol = 1;
1.38      raeburn  2399:         }
                   2400:     } else {
1.45.2.19  raeburn  2401:         if (($mysqlversion > 5) || (($mysqlminorversion == 5) && ($mysqlminorversion > 7)) ||
                   2402:             (($mysqlversion == 5) && ($mysqlminorversion == 7) && ($mysqlsubver > 5))) {
1.38      raeburn  2403:             $usesauth = 1;
1.45.2.19  raeburn  2404:         } elsif (($mysqlversion == 5) &&
                   2405:                  (($mysqlminorversion >= 6) || (($mysqlminorversion == 5) && ($mysqlsubver >= 7)))) {
1.42      raeburn  2406:             $hasauthcol = 1;
1.38      raeburn  2407:         }
                   2408:     }
1.45.2.9  raeburn  2409:     if ($usescreate) {
                   2410:         @mysql_commands = ("CREATE USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
                   2411:     } elsif ($usesauth) {
1.45.2.15  raeburn  2412:         @mysql_commands = ("INSERT user (Host, User, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www','','','','')",
                   2413:                            "FLUSH PRIVILEGES");
1.45.2.2  raeburn  2414:         if ($is_mariadb) {
                   2415:             push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
                   2416:         } else {
                   2417:             push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED WITH mysql_native_password BY 'localhostkey'");
                   2418:         }
1.42      raeburn  2419:     } elsif ($hasauthcol) {
                   2420:         @mysql_commands = ("INSERT user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www',password('localhostkey'),'','','','');");
1.36      raeburn  2421:     } else {
1.42      raeburn  2422:         @mysql_commands = ("INSERT user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject) VALUES('localhost','www',password('localhostkey'),'','','');");
1.36      raeburn  2423:     }
1.1       raeburn  2424:     if ($mysqlversion < 4) {
1.4       raeburn  2425:         push (@mysql_commands,"
                   2426: INSERT db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv) VALUES('localhost','loncapa','www','Y','Y','Y','Y','Y','Y','N','Y','Y','Y')");
                   2427:     } else {
                   2428:         push (@mysql_commands,"
                   2429: INSERT db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Create_tmp_table_priv,Lock_tables_priv) VALUES('localhost','loncapa','www','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y')");
1.1       raeburn  2430:     }
1.4       raeburn  2431:     push(@mysql_commands,"DELETE FROM user WHERE host<>'localhost'");
1.45.2.9  raeburn  2432:     if (($has_pass) || ($mysql_unix_socket)) {
1.1       raeburn  2433:         if ($dbh) {
1.4       raeburn  2434:             push(@mysql_commands,"FLUSH PRIVILEGES");
                   2435:             if (@mysql_commands) {
                   2436:                 foreach my $cmd (@mysql_commands) {
                   2437:                     $dbh->do($cmd) || print $dbh->errstr."\n";
                   2438:                 }
                   2439:             }
                   2440:             if (@mysql_lc_commands) {
                   2441:                 foreach my $lccmd (@mysql_lc_commands) {
                   2442:                     $dbh->do($lccmd) || print $dbh->errstr."\n";
                   2443:                 }
                   2444:             }
1.1       raeburn  2445:             print_and_log(&mt('Permissions set for LON-CAPA MySQL user: [_1]',"'www'")."\n");
                   2446:         } else {
                   2447:             print_and_log(&mt('Problem accessing MySQL.')."\n".
                   2448:                           &mt('Permissions not set.')."\n");
                   2449:         }
                   2450:     } else {
                   2451:         my ($firstpass,$secondpass,$got_passwd,$newmysqlpass);
                   2452:         print &mt('Please enter a root password for the mysql database.')."\n".
                   2453:               &mt('It does not have to match your root account password, but you will need to remember it.')."\n";
                   2454:         my $maxtries = 10;
                   2455:         my $trial = 0;
                   2456:         while ((!$got_passwd) && ($trial < $maxtries)) {
                   2457:             $firstpass = &get_mysql_password(&mt('Enter password'));
                   2458:             if (length($firstpass) > 5) { 
                   2459:                 $secondpass = &get_mysql_password(&mt('Enter password a second time'));
                   2460:                 if ($firstpass eq $secondpass) {
                   2461:                     $got_passwd = 1;
                   2462:                     $newmysqlpass = $firstpass;
                   2463:                 } else {
                   2464:                     print(&mt('Passwords did not match. Please try again.')."\n");
                   2465:                 }
                   2466:                 $trial ++;
                   2467:             } else {
                   2468:                 print(&mt('Password too short.')."\n".
                   2469:                       &mt('Please choose a password with at least six characters.')."\n");
                   2470:             }
                   2471:         }
                   2472:         if ($got_passwd) {
1.45.2.2  raeburn  2473:             my (@newpass_cmds) = &new_mysql_rootpasswd($newmysqlpass,$usesauth,$is_mariadb);
1.4       raeburn  2474:             push(@mysql_commands,@newpass_cmds);
1.1       raeburn  2475:         } else {
                   2476:             print_and_log(&mt('Failed to get MySQL root password from user input.')."\n");
                   2477:         }
                   2478:         if ($dbh) {
1.4       raeburn  2479:             if (@mysql_commands) {
                   2480:                 foreach my $cmd (@mysql_commands) {
                   2481:                     $dbh->do($cmd) || print $dbh->errstr."\n";
                   2482:                 }
                   2483:             }
                   2484:             if (@mysql_lc_commands) {
                   2485:                 foreach my $lccmd (@mysql_lc_commands) {
                   2486:                     $dbh->do($lccmd) || print $dbh->errstr."\n";
                   2487:                 }
                   2488:             }
1.1       raeburn  2489:             if ($got_passwd) {
                   2490:                 print_and_log(&mt('MySQL root password stored.')."\n".
                   2491:                               &mt('Permissions set for LON-CAPA MySQL user: [_1].',"'www'")."\n");
                   2492:             } else {
                   2493:                 print_and_log(&mt('Permissions set for LON-CAPA MySQL user: [_1].',"'www'")."\n");
                   2494:             }
                   2495:         } else {
                   2496:             print_and_log(&mt('Problem accessing MySQL.')."\n".
                   2497:                           &mt('Permissions not set.')."\n");
                   2498:         }
                   2499:     }
                   2500: }
                   2501: 
                   2502: sub new_mysql_rootpasswd {
1.45.2.2  raeburn  2503:     my ($currmysqlpass,$usesauth,$is_mariadb) = @_;
1.36      raeburn  2504:     if ($usesauth) {
1.45.2.2  raeburn  2505:         if ($is_mariadb) {
                   2506:             return ("ALTER USER 'root'\@'localhost' IDENTIFIED BY '$currmysqlpass'",
                   2507:                     "FLUSH PRIVILEGES;");
                   2508:         } else {
                   2509:             return ("ALTER USER 'root'\@'localhost' IDENTIFIED WITH mysql_native_password BY '$currmysqlpass'",
                   2510:                     "FLUSH PRIVILEGES;");
                   2511:         }
1.36      raeburn  2512:     } else {
                   2513:         return ("SET PASSWORD FOR 'root'\@'localhost'=PASSWORD('$currmysqlpass')",
                   2514:                 "FLUSH PRIVILEGES;");
                   2515:     }
1.1       raeburn  2516: }
                   2517: 
                   2518: sub get_mysql_version {
1.45.2.19  raeburn  2519:     my ($version,$minorversion,$subversion,$name);
1.1       raeburn  2520:     if (open(PIPE," mysql -V |")) {
                   2521:         my $info = <PIPE>;
                   2522:         chomp($info);
                   2523:         close(PIPE);
1.45.2.19  raeburn  2524:         ($version,$minorversion,$subversion,$name) = ($info =~ /(\d+)\.(\d+)\.(\d+)(?:\-?(\w*),|)/);
1.1       raeburn  2525:     } else {
                   2526:         print &mt('Could not determine which version of MySQL is installed.').
                   2527:               "\n";
                   2528:     }
1.45.2.19  raeburn  2529:     return ($version,$minorversion,$subversion,$name);
1.1       raeburn  2530: }
                   2531: 
1.45.2.20  raeburn  2532: sub check_systemd_update {
                   2533:     my ($distro) = @_;
                   2534:     my ($use_systemctl,$service);
                   2535:     $service = 'apache2.service';
                   2536:     if ($distro =~ /^ubuntu(\w+)/) {
                   2537:         if ($1 >= 16) {
                   2538:             $use_systemctl = 1;
                   2539:         }
                   2540:     } elsif ($distro =~ /^debian(\w+)/) {
                   2541:         if ($1 >= 9) {
                   2542:             $use_systemctl = 1;
                   2543:         }
                   2544:     } elsif ($distro =~ /^fedora(\d+)/) {
                   2545:         $service = 'httpd.service';
                   2546:         if ($1 >= 16) {
                   2547:             $use_systemctl = 1;
                   2548:         }
                   2549:     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
                   2550:         $service = 'httpd.service';
                   2551:         if ($1 >= 7) {
                   2552:             $use_systemctl = 1;
                   2553:         }
                   2554:     } elsif ($distro =~ /^sles(\d+)/) {
                   2555:         if ($1 >= 12) {
                   2556:             $use_systemctl = 1;
                   2557:         }
                   2558:     } elsif ($distro =~ /^suse(\d+)/) {
                   2559:         if ($1 >= 13) {
                   2560:             $use_systemctl = 1;
                   2561:         }
                   2562:     }
                   2563:     if ($use_systemctl) {
                   2564:         my $needsupdate = &check_systemd_security($distro);
                   2565:         if ($needsupdate) {
                   2566:             if (!-d '/etc/systemd/system/'.$service.'.d') {
                   2567:                 mkdir '/etc/systemd/system/'.$service.'.d', 0755;
                   2568:             }
                   2569:             if (-d '/etc/systemd/system/'.$service.'.d') {
                   2570:                 if (-e '/etc/systemd/system/'.$service.'.d/override.conf') {
                   2571:                     if (open(my $fh,'<','/etc/systemd/system/'.$service.'.d/override.conf')) {
1.45.2.24! raeburn  2572:                         my ($category,$addservice,$needs_update,$linenum,%is_no,%lines,
        !          2573:                             @move,@nocat,@ordered);
        !          2574:                         $linenum = 0;
1.45.2.20  raeburn  2575:                         while (my $entry = <$fh>) {
                   2576:                             $linenum ++;
                   2577:                             chomp($entry);
1.45.2.24! raeburn  2578:                             if ($entry =~ /^\s*\[([^\]]+)\]\s*$/) {
        !          2579:                                 $category = $1;
        !          2580:                                 if ($category =~ /^Service$/i) {
        !          2581:                                     unless (grep(/^Service$/,@ordered)) {
        !          2582:                                         push(@ordered,'Service');
        !          2583:                                     }
1.45.2.20  raeburn  2584:                                 } else {
1.45.2.24! raeburn  2585:                                     unless (grep(/^\Q$category\E$/,@ordered)) {
        !          2586:                                         push(@ordered,$category);
        !          2587:                                     }
1.45.2.20  raeburn  2588:                                 }
1.45.2.24! raeburn  2589:                             } elsif ($entry =~ /^(ProtectHome|RestrictSUIDSGID)\s*=\s*([\w-]+)\s*$/) {
        !          2590:                                 my ($key,$value) = ($1,$2);
        !          2591:                                 next if ($is_no{$key});
        !          2592:                                 if (lc($value) eq 'no') {
        !          2593:                                     if ($category =~ /^Service$/i) {
        !          2594:                                         push(@{$lines{'Service'}},$entry);
1.45.2.20  raeburn  2595:                                     } else {
1.45.2.24! raeburn  2596:                                         push(@move,$entry);
        !          2597:                                         $needs_update = 1;
        !          2598:                                     }
        !          2599:                                 } else {
        !          2600:                                     my $offstr = $key.'=no';
        !          2601:                                     if ($category =~ /^Service$/i) {
        !          2602:                                         push(@{$lines{'Service'}},$offstr);
        !          2603:                                     } else {
        !          2604:                                         push(@move,$offstr);
1.45.2.20  raeburn  2605:                                     }
1.45.2.24! raeburn  2606:                                     $needs_update = 1;
        !          2607:                                 }
        !          2608:                                 $is_no{$key} = $linenum;
        !          2609:                             } else {
        !          2610:                                 next if ($entry =~ /^\s*$/);
        !          2611:                                 if ($category =~ /^Service$/i) {
        !          2612:                                     push(@{$lines{'Service'}},$entry);
        !          2613:                                 } elsif ($category ne '') {
        !          2614:                                     push(@{$lines{$category}},$entry);
        !          2615:                                 } else {
        !          2616:                                     push(@nocat,$entry);
1.45.2.20  raeburn  2617:                                 }
                   2618:                             }
                   2619:                         }
                   2620:                         close($fh);
1.45.2.24! raeburn  2621:                         unless (grep(/^Service$/,@ordered)) {
        !          2622:                             $addservice = 1;
        !          2623:                             unshift(@ordered,'Service');
        !          2624:                         }
        !          2625:                         foreach my $item ('ProtectHome','RestrictSUIDSGID') {
        !          2626:                             unless (exists($is_no{$item})) {
        !          2627:                                 push(@{$lines{'Service'}},$item.'=no');
        !          2628:                                 $needs_update = 1;
        !          2629:                             }
        !          2630:                         }
        !          2631:                         if ($addservice || $needs_update) {
1.45.2.20  raeburn  2632:                             if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {
1.45.2.24! raeburn  2633:                                 if (@ordered) {
        !          2634:                                     foreach my $category (@ordered) {
        !          2635:                                         print $fh "[$category]\n";
        !          2636:                                         if (ref($lines{$category}) eq 'ARRAY') {
        !          2637:                                             foreach my $item (@{$lines{$category}}) {
        !          2638:                                                 print $fh "$item\n";
        !          2639:                                             }
        !          2640:                                         }
        !          2641:                                         if ($category eq 'Service') {
        !          2642:                                             if (@move) {
        !          2643:                                                 foreach my $item (@move) {
        !          2644:                                                     if ($item =~ /^(ProtectHome|RestrictSUIDSGID)\s*=\s*no\s*$/i) {
        !          2645:                                                         my $key = $1;
        !          2646:                                                         unless (grep/^$key\s*=\s*no\s*$/i,@{$lines{$category}}) {
        !          2647:                                                             print $fh "$item\n";
        !          2648:                                                         }
        !          2649:                                                     } else {
        !          2650:                                                         print $fh "$item\n";
        !          2651:                                                     }
        !          2652:                                                 }
        !          2653:                                             }
        !          2654:                                         }
        !          2655:                                         print $fh "\n";
        !          2656:                                     }
1.45.2.20  raeburn  2657:                                 }
1.45.2.24! raeburn  2658:                                 if (@nocat) {
        !          2659:                                     foreach my $item (@nocat) {
        !          2660:                                         print $fh "$item\n";
        !          2661:                                     }
1.45.2.20  raeburn  2662:                                 }
                   2663:                                 close($fh);
                   2664:                                 print_and_log('Updated /etc/systemd/system/'.$service.'.d/override.conf');
1.45.2.21  raeburn  2665:                                 system('systemctl daemon-reload');
1.45.2.20  raeburn  2666:                             } else {
                   2667:                                 print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.');
                   2668:                             }
                   2669:                         } else {
                   2670:                             print_and_log('No change needed in /etc/systemd/system/'.$service.'.d/override.conf');
                   2671:                         }
                   2672:                     } else {
                   2673:                         print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for reading.');
                   2674:                     }
                   2675:                 } else {
                   2676:                     if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {
1.45.2.24! raeburn  2677:                         print $fh '[Service]'."\n".'ProtectHome=no'."\n".'RestrictSUIDSGID=no'."\n";
1.45.2.20  raeburn  2678:                         close($fh);
                   2679:                         print_and_log('Created /etc/systemd/system/'.$service.'.d/override.conf');
1.45.2.21  raeburn  2680:                         system('systemctl daemon-reload');
1.45.2.24! raeburn  2681:                     } else {
        !          2682:                         print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.');
1.45.2.20  raeburn  2683:                     }
                   2684:                 }
                   2685:             } else {
                   2686:                 print_and_log('No /etc/systemd/system/'.$service.'.d directory exists and creating one failed,');
                   2687:             }
                   2688:         } else {
                   2689:             print_and_log('No update needed to systemd security settings for Apache web server.');
                   2690:         }
                   2691:     } else {
                   2692:         print_and_log('No update needed to systemd, as this Linux distro does not use systemctl');
                   2693:     }
                   2694: }
                   2695: 
1.1       raeburn  2696: ###########################################################
                   2697: ##
                   2698: ## RHEL/CentOS/Fedora/Scientific Linux
                   2699: ## Copy LON-CAPA httpd.conf to /etc/httpd/conf
                   2700: ##
                   2701: ###########################################################
                   2702: 
                   2703: sub copy_httpd_conf {
1.14      raeburn  2704:     my ($instdir,$distro) = @_;
                   2705:     my $configfile = 'httpd.conf';
1.45.2.18  raeburn  2706:     if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29      raeburn  2707:         if ($1 >= 7) {
                   2708:             $configfile = 'apache2.4/httpd.conf';
                   2709:         } elsif ($1 > 5) {
1.14      raeburn  2710:             $configfile = 'new/httpd.conf';
                   2711:         }
                   2712:     } elsif ($distro =~ /^fedora(\d+)$/) {
1.29      raeburn  2713:         if ($1 > 17) {
                   2714:             $configfile = 'apache2.4/httpd.conf';
                   2715:         } elsif ($1 > 10) {
1.14      raeburn  2716:             $configfile = 'new/httpd.conf';
                   2717:         }
                   2718:     }
1.1       raeburn  2719:     print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'httpd.conf'",
                   2720:                   "'/etc/httpd/conf/httpd.conf'")."\n");
                   2721:     copy "/etc/httpd/conf/httpd.conf","/etc/httpd/conf/httpd.conf.original";
1.14      raeburn  2722:     copy "$instdir/centos-rhes-fedora-sl/$configfile","/etc/httpd/conf/httpd.conf";
1.5       raeburn  2723:     chmod(0444,"/etc/httpd/conf/httpd.conf");
1.1       raeburn  2724:     print_and_log("\n");
                   2725: }
                   2726: 
1.45.2.5  raeburn  2727: ###########################################################
                   2728: ##
                   2729: ## RHEL/CentOS/Fedora/Scientific Linux
                   2730: ## Copy LON-CAPA mpm.conf to /etc/httpd/conf.modules.d/00-mpm.conf
                   2731: ##
                   2732: ## The LON-CAPA mpm.conf enables the prefork MPM module in
                   2733: ## Apache. This is also the default for RHEL/CentOS/Oracle
                   2734: ## Linux 7 and earlier, and Fedora 26 and earlier. For more
                   2735: ## recent versions of those distros, the event MPM is enabled
                   2736: ## by default. After &copy_mpm_conf() is run, the prefork MPM
                   2737: ## module will be enabled instead of the event MPM module.
                   2738: ##
                   2739: ###########################################################
                   2740: 
                   2741: sub copy_mpm_conf {
                   2742:     my ($instdir,$distro) = @_;
                   2743:     my $mpmfile = 'mpm.conf';
                   2744:     if ((-e "/etc/httpd/conf.modules.d/00-mpm.conf") &&
                   2745:         (-e "$instdir/centos-rhes-fedora-sl/$mpmfile")) {
                   2746:         print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'mpm.conf'",
                   2747:                       "'/etc/httpd/conf.modules.d/00-mpm.conf'")."\n");
                   2748:         copy "$instdir/centos-rhes-fedora-sl/$mpmfile","/etc/httpd/conf.modules.d/00-mpm.conf";
                   2749:         chmod(0644,"/etc/httpd/conf.modules.d/00-mpm.conf");
                   2750:         print_and_log("\n");
                   2751:     } else {
                   2752:         my $logfail;
1.45.2.18  raeburn  2753:         if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.45.2.5  raeburn  2754:             if ($1 > 7) {
                   2755:                 $logfail = 1;
                   2756:             }
                   2757:         } elsif ($distro =~ /^fedora(\d+)$/) {
                   2758:             if ($1 > 26) {
                   2759:                 $logfail = 1;
                   2760:             }
                   2761:         }
                   2762:         if ($logfail) {
                   2763:             print_and_log(&mt('Warning: copying the LON-CAPA [_1] failed because [_2] and/or [_3] are missing.',
                   2764:                               $mpmfile,"'$instdir/centos-rhes-fedora-sl/$mpmfile'",
                   2765:                               "'/etc/httpd/conf.modules.d/00-mpm.conf'"));
                   2766:             print_and_log("\n");
                   2767:         }
                   2768:     }
                   2769: }
                   2770: 
1.1       raeburn  2771: #########################################################
                   2772: ##
1.17      raeburn  2773: ## Ubuntu/Debian -- copy our loncapa configuration file to
1.1       raeburn  2774: ## sites-available and set the symlink from sites-enabled.
                   2775: ##
                   2776: #########################################################
                   2777: 
                   2778: sub copy_apache2_debconf {
1.28      raeburn  2779:     my ($instdir,$distro) = @_;
1.6       raeburn  2780:     my $apache2_mods_enabled_dir = '/etc/apache2/mods-enabled';
                   2781:     my $apache2_mods_available_dir = '/etc/apache2/mods-available';
                   2782:     foreach my $module ('headers.load','expires.load') {
                   2783:         unless (-l "$apache2_mods_enabled_dir/$module") {
                   2784:             symlink("$apache2_mods_available_dir/$module","$apache2_mods_enabled_dir/$module");
                   2785:             print_and_log(&mt('Enabling "[_1]" Apache module.',$module)."\n");
                   2786:         }
                   2787:     }
1.28      raeburn  2788:     my $apache2_sites_enabled_dir = '/etc/apache2/sites-enabled';
                   2789:     my $apache2_sites_available_dir = '/etc/apache2/sites-available';
                   2790:     my $defaultconfig = "$apache2_sites_enabled_dir/000-default";
1.45.2.10  raeburn  2791:     my $defaultsite = "$apache2_sites_enabled_dir/loncapa.conf";
1.28      raeburn  2792:     my ($distname,$version);
                   2793:     if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
                   2794:         $distname = $1;
                   2795:         $version = $2;
                   2796:     }
1.45.2.19  raeburn  2797:     if ((($distname eq 'ubuntu') && ($version > 12)) ||
                   2798:         (($distname eq 'debian') && ($version >= 10))) {
1.28      raeburn  2799:         $defaultconfig = "$apache2_sites_enabled_dir/000-default.conf";
                   2800:     }
1.45.2.7  raeburn  2801:     my ($skipconf,$skipsite,$skipstatus);
1.45.2.19  raeburn  2802:     if ((($distname eq 'ubuntu') && ($version > 12)) ||
                   2803:         (($distname eq 'debian') && ($version >= 10))) {
1.28      raeburn  2804:         my $apache2_conf_enabled_dir = '/etc/apache2/conf-enabled';
                   2805:         my $apache2_conf_available_dir = '/etc/apache2/conf-available';
1.33      raeburn  2806:         my $defaultconf = $apache2_conf_enabled_dir.'/loncapa.conf';
1.45.2.7  raeburn  2807:         if ((-e "$apache2_conf_available_dir/loncapa") && (-e "$instdir/debian-ubuntu/ubuntu14/loncapa_conf")) {
1.45.2.8  raeburn  2808:             if (open(PIPE, "diff --brief $apache2_conf_available_dir/loncapa $instdir/debian-ubuntu/ubuntu14/loncapa_conf |")) {
1.45.2.7  raeburn  2809:                 my $diffres = <PIPE>;
                   2810:                 close(PIPE);
                   2811:                 chomp($diffres);
                   2812:                 if ($diffres) {
1.45.2.10  raeburn  2813:                     copy("$apache2_conf_available_dir/loncapa","$apache2_conf_available_dir/loncapa.conf.original");
                   2814:                 } else {
                   2815:                     copy("$apache2_conf_available_dir/loncapa","$apache2_conf_available_dir/loncapa.conf");
1.45.2.11  raeburn  2816:                     chdir($apache2_conf_enabled_dir);
                   2817:                     symlink('../conf-available/loncapa.conf','loncapa.conf');
                   2818:                     chdir($instdir);
1.45.2.7  raeburn  2819:                 }
                   2820:                 if (-l $defaultconf) {
                   2821:                     my $linkfname = readlink($defaultconf);
1.45.2.11  raeburn  2822:                     if ($linkfname ne '') {
                   2823:                         $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_conf_enabled_dir));
                   2824:                     }
1.45.2.7  raeburn  2825:                     if ($linkfname eq "$apache2_conf_available_dir/loncapa") {
1.45.2.10  raeburn  2826:                         unlink($defaultconf);
                   2827:                     }
                   2828:                 }
                   2829:                 unlink("$apache2_conf_available_dir/loncapa");
                   2830:             }
                   2831:         }
                   2832:         if ((-e "$apache2_conf_available_dir/loncapa.conf") && (-e "$instdir/debian-ubuntu/ubuntu14/loncapa_conf")) {
                   2833:             if (open(PIPE, "diff --brief $apache2_conf_available_dir/loncapa.conf $instdir/debian-ubuntu/ubuntu14/loncapa_conf |")) {
                   2834:                 my $diffres = <PIPE>;
                   2835:                 close(PIPE);
                   2836:                 chomp($diffres);
                   2837:                 if ($diffres) {
                   2838:                     copy("$apache2_conf_available_dir/loncapa.conf","$apache2_conf_available_dir/loncapa.conf.original");
                   2839:                 }
                   2840:                 if (-l $defaultconf) {
                   2841:                     my $linkfname = readlink($defaultconf);
1.45.2.11  raeburn  2842:                     if ($linkfname ne '') {
                   2843:                         $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_conf_enabled_dir));
                   2844:                     }
1.45.2.10  raeburn  2845:                     if ($linkfname eq "$apache2_conf_available_dir/loncapa.conf") {
1.45.2.7  raeburn  2846:                         unless ($diffres) {
                   2847:                             $skipconf = 1;
                   2848:                         }
                   2849:                     }
                   2850:                 }
                   2851:             }
                   2852:         }
                   2853:         unless ($skipconf) {
                   2854:             print_and_log(&mt('Copying loncapa [_1] config file to [_2] and pointing [_3] to it from conf-enabled.',"'apache2'","'/etc/apache2/conf-available'","'loncapa.conf symlink'")."\n");
1.45.2.10  raeburn  2855:             copy("$instdir/debian-ubuntu/ubuntu14/loncapa_conf","$apache2_conf_available_dir/loncapa.conf");
                   2856:             chmod(0444,"$apache2_conf_available_dir/loncapa.conf");
1.45.2.7  raeburn  2857:             if (-l $defaultconf) {
                   2858:                 unlink($defaultconf);
                   2859:             }
1.45.2.11  raeburn  2860:             chdir($apache2_conf_enabled_dir);
                   2861:             symlink('../conf-available/loncapa.conf','loncapa.conf');
                   2862:             chdir($instdir);
1.45.2.7  raeburn  2863:         }
                   2864:         my $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_site";
                   2865:         if ((-e $stdsite) && (-e "$apache2_sites_available_dir/loncapa")) {
                   2866:             if (open(PIPE, "diff --brief $stdsite $apache2_sites_available_dir/loncapa |")) {
                   2867:                 my $diffres = <PIPE>;
                   2868:                 close(PIPE);
                   2869:                 chomp($diffres);
                   2870:                 if ($diffres) {
1.45.2.10  raeburn  2871:                     copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.conf.original");
                   2872:                 } else {
                   2873:                     copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.conf");
1.45.2.7  raeburn  2874:                 }
                   2875:                 if (-l $defaultconfig) {
                   2876:                     my $linkfname = readlink($defaultconfig);
1.45.2.11  raeburn  2877:                     if ($linkfname ne '') {
                   2878:                         $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
                   2879:                     }
1.45.2.7  raeburn  2880:                     if ($linkfname eq "$apache2_sites_available_dir/loncapa") {
1.45.2.10  raeburn  2881:                         unlink($defaultconfig);
                   2882:                     }
                   2883:                 }
                   2884:                 unlink("$apache2_sites_available_dir/loncapa");
                   2885:             }
                   2886:         }
                   2887:         if ((-e $stdsite) && (-e "$apache2_sites_available_dir/loncapa.conf")) {
                   2888:             if (open(PIPE, "diff --brief $stdsite $apache2_sites_available_dir/loncapa.conf |")) {
                   2889:                 my $diffres = <PIPE>;
                   2890:                 close(PIPE);
                   2891:                 chomp($diffres);
                   2892:                 if ($diffres) {
                   2893:                     copy("$apache2_sites_available_dir/loncapa.conf","$apache2_sites_available_dir/loncapa.conf.original");
                   2894:                 }
                   2895:                 if (-l $defaultsite) {
                   2896:                     my $linkfname = readlink($defaultsite);
1.45.2.11  raeburn  2897:                     if ($linkfname ne '') {
                   2898:                         $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
                   2899:                     }
                   2900:                     if ($linkfname eq "$apache2_sites_available_dir/loncapa.conf") {
1.45.2.7  raeburn  2901:                         unless ($diffres) {
                   2902:                             $skipsite = 1;
                   2903:                         }
                   2904:                     }
                   2905:                 }
                   2906:             }
                   2907:         }
                   2908:         unless ($skipsite) {
1.45.2.10  raeburn  2909:             print_and_log(&mt('Copying loncapa [_1] site file to [_2] and pointing [_3] to it from sites-enabled.',"'apache2'","'/etc/apache2/sites-available'","'loncapa.conf symlink'")."\n");
                   2910:             copy("$instdir/debian-ubuntu/ubuntu14/loncapa_site","$apache2_sites_available_dir/loncapa.conf");
                   2911:             chmod(0444,"$apache2_sites_available_dir/loncapa.conf");
1.45.2.11  raeburn  2912:             chdir($apache2_sites_enabled_dir);
                   2913:             symlink('../sites-available/loncapa.conf','loncapa.conf');
                   2914:             chdir($instdir);
1.45.2.10  raeburn  2915:         }
1.45.2.11  raeburn  2916:         if (-l $defaultconfig) {
1.45.2.10  raeburn  2917:             my $linkfname = readlink($defaultconfig);
1.45.2.11  raeburn  2918:             if ($linkfname ne '') {
                   2919:                 $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
                   2920:             }
                   2921:             if ($linkfname eq "$apache2_sites_available_dir/000-default.conf") {
1.45.2.10  raeburn  2922:                 unlink($defaultconfig);
                   2923:             }
1.45.2.7  raeburn  2924:         }
                   2925:     } else {
                   2926:         if ((-e "$instdir/debian-ubuntu/loncapa") && (-e "$apache2_sites_available_dir/loncapa")) {
                   2927:             if (open(PIPE, "diff --brief $instdir/debian-ubuntu/loncapa $apache2_sites_available_dir/loncapa |")) {
                   2928:                 my $diffres = <PIPE>;
                   2929:                 close(PIPE);
                   2930:                 chomp($diffres);
                   2931:                 if ($diffres) {
                   2932:                     copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.original");
                   2933:                 }
                   2934:                 if (-l $defaultconfig) {
                   2935:                     my $linkfname = readlink($defaultconfig);
                   2936:                     if ($linkfname eq "$apache2_sites_available_dir/loncapa") {
                   2937:                         unless ($diffres) {
                   2938:                             $skipsite = 1;
                   2939:                         }
                   2940:                     }
                   2941:                 }
                   2942:             }
                   2943:         }
                   2944:         unless ($skipsite) {
                   2945:             if (-l $defaultconfig) {
                   2946:                 unlink($defaultconfig);
                   2947:             }
                   2948:             print_and_log(&mt('Copying loncapa [_1] config file to [_2] and pointing [_3] to it from sites-enabled.',"'apache2'","'/etc/apache2/sites-available'","'000-default symlink'")."\n");
                   2949:             if (-e "$instdir/debian-ubuntu/loncapa") {
                   2950:                 copy("$instdir/debian-ubuntu/loncapa","$apache2_sites_available_dir/loncapa");
                   2951:                 chmod(0444,"$apache2_sites_available_dir/loncapa");
                   2952:                 symlink("$apache2_sites_available_dir/loncapa","$apache2_sites_enabled_dir/000-default");
                   2953:             }
                   2954:         }
                   2955:     }
1.45.2.19  raeburn  2956:     if (($distname eq 'ubuntu') || ($distname eq 'debian')) {
1.45.2.7  raeburn  2957:         my $sitestatus = "$apache2_mods_available_dir/status.conf";
                   2958:         my $stdstatus = "$instdir/debian-ubuntu/status.conf";
                   2959:         if ((-e $sitestatus) && (-e $stdstatus)) {
                   2960:             if (open(PIPE, "diff --brief $stdstatus $sitestatus |")) {
                   2961:                 my $diffres = <PIPE>;
                   2962:                 close(PIPE);
                   2963:                 chomp($diffres);
                   2964:                 if ($diffres) {
                   2965:                     copy("$apache2_mods_available_dir/status.conf","$apache2_mods_available_dir/status.conf.original");
                   2966:                 } else {
                   2967:                     $skipstatus = 1;
                   2968:                 }
                   2969:             }
                   2970:         }
                   2971:         unless ($skipstatus) {
                   2972:             if (-e $stdstatus) {
                   2973:                 print_and_log(&mt('Copying loncapa [_1] file to [_2],',"'status.conf'","'/etc/apache2/mods-available/status.conf'")."\n");
                   2974:                 copy($stdstatus,$sitestatus);
                   2975:                 chmod(0644,$sitestatus);
                   2976:             }
                   2977:         }
1.28      raeburn  2978:     }
1.1       raeburn  2979:     print_and_log("\n");
                   2980: }
                   2981: 
                   2982: ###########################################################
                   2983: ##
                   2984: ## openSuSE/SLES Copy apache2 config files:
                   2985: ##   default-server.conf, uid.conf, /etc/sysconfig/apache2 
                   2986: ##   and create symlink from /srv/www/conf to /etc/apache2 
                   2987: ##
                   2988: ###########################################################
                   2989: 
                   2990: sub copy_apache2_suseconf {
1.45.2.1  raeburn  2991:     my ($instdir,$distro) = @_;
                   2992:     my ($name,$version) = ($distro =~ /^(suse|sles)([\d\.]+)$/);
                   2993:     my $conf_file = "$instdir/sles-suse/default-server.conf";
                   2994:     if (($name eq 'sles') && ($version >= 12)) {
                   2995:         $conf_file = "$instdir/sles-suse/apache2.4/default-server.conf";
                   2996:     }
1.1       raeburn  2997:     print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',
                   2998:                   "'default-server.conf'",
                   2999:                   "'/etc/apache2/default-server.conf'")."\n");
                   3000:     if (!-e "/etc/apache2/default-server.conf.original") {
                   3001:         copy "/etc/apache2/default-server.conf","/etc/apache2/default-server.conf.original";
                   3002:     }
1.45.2.1  raeburn  3003:     copy $conf_file,"/etc/apache2/default-server.conf";
1.5       raeburn  3004:     chmod(0444,"/etc/apache2/default-server.conf");
1.1       raeburn  3005:     # Make symlink for conf directory (included in loncapa_apache.conf)
                   3006:     my $can_symlink = (eval { symlink('/etc/apache2','/srv/www/conf'); }, $@ eq '');
                   3007:     if ($can_symlink) {
                   3008:         &print_and_log(&mt('Symlink created for [_1] to [_2].',
                   3009:                        "'/srv/www/conf'","'/etc/apache2'")."\n");
                   3010:     } else {
                   3011:         &print_and_log(&mt('Symlink creation failed for [_1] to [_2]. You will need to perform this action from the command line.',"'/srv/www/conf'","'/etc/apache2'")."\n");
                   3012:     }
                   3013:     &copy_apache2_conf_files($instdir);
1.45.2.1  raeburn  3014:     &copy_sysconfig_apache2_file($instdir,$name,$version); 
1.1       raeburn  3015:     print_and_log("\n");
                   3016: }
                   3017: 
                   3018: ###############################################
                   3019: ##
                   3020: ## Modify uid.conf
                   3021: ##
                   3022: ###############################################
                   3023: sub copy_apache2_conf_files {
                   3024:     my ($instdir) = @_;
                   3025:     print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',
                   3026:                   "'uid.conf'","'/etc/apache2/uid.conf'")."\n");
                   3027:     if (!-e "/etc/apache2/uid.conf.original") {
                   3028:         copy "/etc/apache2/uid.conf","/etc/apache2/uid.conf.original";
                   3029:     }
1.9       raeburn  3030:     copy "$instdir/sles-suse/uid.conf","/etc/apache2/uid.conf";
1.5       raeburn  3031:     chmod(0444,"/etc/apache2/uid.conf");
1.1       raeburn  3032: }
                   3033: 
                   3034: ###############################################
                   3035: ##
                   3036: ## Modify /etc/sysconfig/apache2  
                   3037: ##
                   3038: ###############################################
                   3039: sub copy_sysconfig_apache2_file {
1.45.2.1  raeburn  3040:     my ($instdir,$name,$version) = @_;
1.1       raeburn  3041:     print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'sysconfig/apache2'","'/etc/sysconfig/apache2'")."\n");
                   3042:     if (!-e "/etc/sysconfig/apache2.original") {
                   3043:         copy "/etc/sysconfig/apache2","/etc/sysconfig/apache2.original";
                   3044:     }
1.45.2.1  raeburn  3045:     my $sysconf_file = "$instdir/sles-suse/sysconfig_apache2";
                   3046:     if (($name eq 'sles') && ($version >= 12)) {
                   3047:        $sysconf_file = "$instdir/sles-suse/apache2.4/sysconfig_apache2";
                   3048:     }
                   3049:     copy $sysconf_file,"/etc/sysconfig/apache2";
1.5       raeburn  3050:     chmod(0444,"/etc/sysconfig/apache2");
1.1       raeburn  3051: }
                   3052: 
                   3053: ###############################################
                   3054: ##
                   3055: ## Add/Modify /etc/insserv/overrides
                   3056: ##
                   3057: ###############################################
                   3058: 
                   3059: sub update_SuSEfirewall2_setup {
                   3060:     my ($instdir) = @_;
                   3061:     print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'SuSEfirewall2_setup'","'/etc/insserv/overrides/SuSEfirewall2_setup'")."\n");
                   3062:     if (!-e "/etc/insserv/overrides/SuSEfirewall2_setup") {
                   3063:         if (!-d "/etc/insserv") {
                   3064:             mkdir("/etc/insserv",0755); 
                   3065:         }
                   3066:         if (!-d "/etc/insserv/overrides") {
                   3067:             mkdir("/etc/insserv/overrides",0755);
                   3068:         }
                   3069:     } elsif (!-e  "/etc/insserv/overrides/SuSEfirewall2_setup.original") {
                   3070:         copy "/etc/insserv/overrides/SuSEfirewall2_setup","/etc/insserv/overrides/SuSEfirewall2_setup.original"
                   3071:     }
1.9       raeburn  3072:     copy "$instdir/sles-suse/SuSEfirewall2_setup","/etc/insserv/overrides/SuSEfirewall2_setup";
1.5       raeburn  3073:     chmod(0444,"/etc/insserv/overrides/SuSEfirewall2_setup");
                   3074: }
                   3075: 
                   3076: sub get_iptables_rules {
                   3077:     my ($distro,$instdir,$apachefw) = @_;
                   3078:     my (@fwchains,@ports);
                   3079:     if (&firewall_is_active()) {
                   3080:         my $iptables = &get_pathto_iptables();
                   3081:         if ($iptables ne '') {
                   3082:             @fwchains = &get_fw_chains($iptables,$distro);
                   3083:         }
                   3084:     }
                   3085:     if (ref($apachefw) eq 'HASH') {
                   3086:         foreach my $service ('http','https') {
                   3087:             unless ($apachefw->{$service}) {
                   3088:                 push (@ports,$service); 
                   3089:             }
                   3090:         }
                   3091:     } else {
                   3092:         @ports = ('http','https');
                   3093:     }
                   3094:     if (@ports == 0) {
                   3095:         return;
                   3096:     }
                   3097:     my $ask_to_enable;
                   3098:     if (-e "/etc/iptables.loncapa.rules") {
1.9       raeburn  3099:         if (open(PIPE, "diff --brief $instdir/debian-ubuntu/iptables.loncapa.rules /etc/iptables.loncapa.rules |")) {
1.5       raeburn  3100:             my $diffres = <PIPE>;
                   3101:             close(PIPE);
                   3102:             chomp($diffres);
                   3103:             if ($diffres) {
                   3104:                 print &mt('Warning: [_1] exists but differs from LON-CAPA supplied file.','/etc/iptables.loncapa.rules')."\n";
                   3105:             }
                   3106:         } else {
                   3107:             print &mt('Error: unable to open [_1] to compare contents with LON-CAPA supplied file.','/etc/iptables.loncapa.rules')."\n";
                   3108:         }
                   3109:     } else {
1.9       raeburn  3110:         if (-e "$instdir/debian-ubuntu/iptables.loncapa.rules") {
                   3111:             copy "$instdir/debian-ubuntu/iptables.loncapa.rules","/etc/iptables.loncapa.rules";
1.5       raeburn  3112:             chmod(0600,"/etc/iptables.loncapa.rules");
                   3113:         }
                   3114:     }
                   3115:     if (-e "/etc/iptables.loncapa.rules") {
                   3116:         if (-e "/etc/network/if-pre-up.d/iptables") {
1.9       raeburn  3117:             if (open(PIPE, "diff --brief $instdir/debian-ubuntu/iptables /etc/network/if-pre-up/iptables |")) {
1.5       raeburn  3118:                 my $diffres = <PIPE>;
                   3119:                 close(PIPE);
                   3120:                 chomp($diffres);
                   3121:                 if ($diffres) {
                   3122:                     print &mt('Warning: [_1] exists but differs from LON-CAPA supplied file.','/etc/network/if-pre-up.d/iptables')."\n";
                   3123:                 }
                   3124:             } else {
                   3125:                 print &mt('Error: unable to open [_1] to compare contents with LON-CAPA supplied file.','/etc/network/if-pre-up.d/iptables')."\n";
                   3126:             }
                   3127:         } else {
1.9       raeburn  3128:             copy "$instdir/debian-ubuntu/iptables","/etc/network/if-pre-up.d/iptables";
1.5       raeburn  3129:             chmod(0755,"/etc/network/if-pre-up.d/iptables");
                   3130:             print_and_log(&mt('Installed script "[_1]" to add iptables rules to block all ports except 22, 80, and 443 when network is enabled during boot.','/etc/network/if-pre-up.d/iptables'));
                   3131:             $ask_to_enable = 1;
                   3132:         }
                   3133:     }
                   3134:     return $ask_to_enable;
1.1       raeburn  3135: }
                   3136: 
                   3137: sub download_loncapa {
                   3138:     my ($instdir,$lctarball) = @_;
                   3139:     my ($have_tarball,$updateshown);
                   3140:     if (! -e "$instdir/$lctarball") {
                   3141: 	print_and_log(&mt('Retrieving LON-CAPA source files from: [_1]',
                   3142: 		      'http://install.loncapa.org')."\n");
                   3143: 	system("wget http://install.loncapa.org/versions/$lctarball ".
                   3144: 	       "2>/dev/null 1>/dev/null");
                   3145: 	if (! -e "./$lctarball") {
                   3146: 	    print &mt('Unable to retrieve LON-CAPA source files from: [_1].', 
                   3147: 		     "http://install.loncapa.org/versions/$lctarball")."\n";
                   3148: 	} else {
                   3149:             $have_tarball = 1;
                   3150:         }
                   3151: 	print_and_log("\n");
                   3152:     } else {
                   3153:         $have_tarball = 1;
                   3154: 	print_and_log("
                   3155: ------------------------------------------------------------------------
                   3156: 
1.45.2.16  raeburn  3157: ".&mt('You seem to have a version of [_1] in [_2]',$lctarball,$instdir)."\n".
1.1       raeburn  3158: &mt('This copy will be used and a new version will NOT be downloaded.')."\n".
                   3159: &mt('If you wish, you may download a new version by executing:')."
                   3160: 
1.45.2.16  raeburn  3161: wget http://install.loncapa.org/versions/$lctarball
1.1       raeburn  3162: 
                   3163: ------------------------------------------------------------------------
                   3164: ");
                   3165:     }
                   3166: 
                   3167:     ##
1.45.2.16  raeburn  3168:     ## untar loncapa-X.Y.Z.tar.gz
1.1       raeburn  3169:     ##
                   3170:     if ($have_tarball) {
1.45.2.16  raeburn  3171:         my $homedir = '/root';
                   3172:         my ($targetdir,$chdircmd,$updatecmd);
                   3173:         if (($distro =~ /^ubuntu/) && ($instdir ne $homedir)) {
                   3174:             ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
                   3175:             $updatecmd = 'sudo ./UPDATE';
                   3176:         } else {
                   3177:             $updatecmd = './UPDATE';
                   3178:         }
1.1       raeburn  3179:         print_and_log(&mt('Extracting LON-CAPA source files')."\n");
1.45.2.16  raeburn  3180:         if (-e $homedir) {
                   3181:             writelog(`tar zxf $instdir/$lctarball --directory $homedir`);
                   3182:             $targetdir = $homedir;
                   3183:         } else {
                   3184:             writelog(`tar zxf $instdir/$lctarball`);
                   3185:             $targetdir = $instdir;
                   3186:         }
                   3187:         if ($lctarball =~ /^loncapa\-(\d+\.\d+\.\d+(?:|[^.]+))\.tar\.gz$/) {
                   3188:             $chdircmd = "cd $targetdir/loncapa-".$1;
                   3189:         } else {
                   3190:             $chdircmd = "cd $targetdir/loncapa-X.Y.Z  (X.Y.Z should correspond to a version number like '2.11.3')";
                   3191:         }
1.1       raeburn  3192:         print_and_log("\n");
                   3193:         print &mt('LON-CAPA source files extracted.')."\n".
1.45.2.16  raeburn  3194:               &mt('It remains for you to execute the following commands:').
                   3195:               "\n$chdircmd\n$updatecmd\n".
                   3196:               &mt('If you have any trouble, please see [_1] and [_2]',
                   3197:                   'http://install.loncapa.org/','http://help.loncapa.org/')."\n";
1.1       raeburn  3198:         $updateshown = 1;
                   3199:     }
                   3200:     return ($have_tarball,$updateshown);
                   3201: }
                   3202: 
                   3203: close LOG;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>