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

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

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