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