--- loncom/debugging_tools/modify_config_files.pl 2004/08/10 20:26:02 1.2 +++ loncom/debugging_tools/modify_config_files.pl 2024/07/31 03:39:20 1.29 @@ -2,7 +2,7 @@ # # The LearningOnline Network # -# $Id: modify_config_files.pl,v 1.2 2004/08/10 20:26:02 matthew Exp $ +# $Id: modify_config_files.pl,v 1.29 2024/07/31 03:39:20 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,45 +36,466 @@ B =head1 SYNOPSIS -This script modifies /etc/yum.conf and /etc/my.cnf. +This script modifies local MySQL configuration file(s), which will be: +/home/www/.my.cnf and, depending on distro/version also one of: +/etc/my.cnf, /etc/mysql/my.cnf, /etc/mysql/mysql.conf.d/mysqld.cnf, +or /etc/mysql/mariadb.conf.d/50-server.cnf, and also the file used to +store information about the LON-CAPA package repositories located at +install.loncapa.org. which provide rpm or deb packages created for the +Linux distro/version being used. The file to modify will be one of: +/etc/yum.conf (for CentOS/Scientific Linux/RHEL >=5 and <8), +/etc/apt/sources.list (for Debian < 10 and Ubuntu < 22), or +/etc/apt/sources.list.d/loncapa.list (for Debian >= 10 and Ubuntu > 20), +/etc/sysconfig/rhn/sources (for RHEL4), or /etc/yum.repos.d/loncapa.repo +(for Fedora >= 21; Oracle Linux; AlmaLinux; RockyLinux; CentOS/RHEL >= 8). + +The script also modifies /home/www/.inputrc on Linux distros which have +readline 8.1 or newer, i.e., CentOS/Scientific Linux/RHEL >= 9, +Ubuntu >= 22, Debian >= 12, and Fedora >= 34. =head1 DESCRIPTION -This script modifies /etc/yum.conf and /etc/my.cnf to ensure certain parameters -are set properly. The LON-CAPA yum repositories are added to /etc/yum.conf. -The /etc/my.cnf file is modified to set the wait_timeout to 1 year. Backup -copies of each file are made in /etc. +This script will modify /etc/my.cnf, /etc/mysql/my.cnf, +/etc/mysql/mysql.conf.d/mysqld.cnf, or +/etc/mysql/mariadb.conf.d/50-server.cnf, +and /etc/yum.conf, /etc/yum.repos.d/loncapa.repo, +/etc/apt/sources.list, /etc/apt/sources.list.d/loncapa.list or +/etc/sysconfig/rhn/sources and /home/www/.inputrc to ensure +certain parameters are set properly. + +The LON-CAPA yum repositories are added to /etc/yum.conf, +/etc/yum.repos.d/loncapa.repo, or /etc/sysconfig/rhn/sources +and the LON-CAPA apt repositories are added to +/etc/apt/sources.list or /etc/apt/sources.list.d/loncapa.list. + +The /etc/my.cnf, /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf +or /etc/mysql/mariadb.conf.d/50-server.cnf file is modified to set the +wait_timeout to 1 year. Backup copies of each file are made in +/etc, /etc/apt, and /etc/sysconfig/rhn, as appropriate. =cut use strict; use File::Copy; - -&update_file('/etc/yum.conf', - [{section => 'loncapa-updates-i386', +use lib '/home/httpd/lib/perl/'; +use LONCAPA::Configuration; +my $loncapa_config=LONCAPA::Configuration::read_conf('loncapa.conf'); + +open(DSH,"$$loncapa_config{'lonDaemons'}/distprobe |"); +my $dist = ; +chomp($dist); +close(DSH); + +my $yum_status; +my $loninst = 'http://install.loncapa.org'; +my $loninst_re = 'http://install\.loncapa\.org'; +if ($dist =~ /^fedora(\d+)$/) { + my $file = '/etc/yum.conf'; + my $ver = $1; + my $gpgchk = '0'; + my $gpg = "$loninst/versions/fedora/RPM-GPG-KEY-loncapa"; + my $nobackup; + if ($ver > 6) { + $gpgchk = '1'; + } + if ($ver >= 21) { + $file = '/etc/yum.repos.d/loncapa.repo'; + $nobackup = 1; + } + $yum_status = + &update_file($file, + [{section => 'loncapa-updates-basearch', key => 'name=', - value => 'Fedora Core $releasever LON-CAPA i386 Updates', - }, {section => 'loncapa-updates-i386', + value => 'Fedora Core $releasever LON-CAPA $basearch Updates', + }, {section => 'loncapa-updates-basearch', key => 'baseurl=', - value => 'http://install.loncapa.org/fedora/linux/loncapa/'. - '$releasever/i386', + value => $loninst.'/fedora/linux/loncapa/$releasever/$basearch', + }, {section => 'loncapa-updates-basearch', + key => 'gpgcheck=', + value => $gpgchk, + }, {section => 'loncapa-updates-basearch', + key => 'gpgkey=', + value => $gpg, }, {section => 'loncapa-updates-noarch', key => 'name=', value => 'Fedora Core $releasever LON-CAPA noarch Updates', }, {section => 'loncapa-updates-noarch', key => 'baseurl=', - value => 'http://install.loncapa.org/fedora/linux/loncapa/'. - '$releasever/noarch', - }]); - -&update_file('/etc/my.cnf', - [{section =>'mysqld', - key =>'set-variable=wait_timeout=', - value =>'31536000', }]); + value => $loninst.'/fedora/linux/loncapa/$releasever/noarch', + }, {section => 'loncapa-updates-noarch', + key => 'gpgcheck=', + value => $gpgchk, + }, {section => 'loncapa-updates-noarch', + key => 'gpgkey=', + value => $gpg, + }],$nobackup); +} elsif ($dist =~ /^(rhes|centos|scientific|oracle|rocky|alma)(\d+)(|\-stream)$/) { + my $type = $1; + my $ver = $2; + my $stream = $3; + my $longver = $ver; + my $nobackup; + if ($type eq 'rhes') { + if ($ver == 4) { + $longver = '4ES'; + } elsif ($ver == 5) { + $longver = '5Server'; + } + } elsif ($type eq 'centos') { + $type .= $stream; + } + my %info = ( + rhes => { + title => 'RHEL', + path => 'redhat/linux/enterprise/loncapa', + gpg => 'versions/redhat/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + centos => { + title => 'CentOS', + path => 'centos/loncapa', + gpg => 'versions/centos/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + scientific => { + title => 'Scientific Linux', + path => 'scientific/loncapa', + gpg => 'versions/scientific/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + oracle => { + title => 'Oracle Linux', + path => 'oracle/loncapa', + gpg => 'versions/oracle/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + rocky => { + title => 'Rocky Linux', + path => 'rocky/loncapa', + gpg => 'versions/rocky/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + alma => { + title => 'AlmaLinux', + path => 'alma/loncapa', + gpg => 'versions/alma/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + 'centos-stream' => { + title => 'CentOS Stream', + path => 'centos/loncapa', + gpg => 'versions/centos/RPM-GPG-KEY-loncapa', + gpgchk => 1, + }, + ); + if (ref($info{$type}) eq 'HASH') { + if ($ver > 4) { + my $file = '/etc/yum.conf'; + if (($ver > 7) || ($type eq 'oracle') || ($type eq 'rocky') || + ($type eq 'alma') || ($type eq 'centos-stream')) { + $file = '/etc/yum.repos.d/loncapa.repo'; + $nobackup = 1; + } + my $release = '$releasever'; + if ($type eq 'centos-stream') { + $release .= '-stream'; + } + $yum_status = + &update_file($file, + [{section => 'loncapa-updates-basearch', + key => 'name=', + value => $info{$type}{title}.' $releasever LON-CAPA $basearch Updates', + }, {section => "loncapa-updates-basearch", + key => 'baseurl=', + value => "$loninst/$info{$type}{path}/$release/".'$basearch', + }, {section => 'loncapa-updates-basearch', + key => 'gpgcheck=', + value => $info{$type}{gpgchk}, + }, {section => 'loncapa-updates-basearch', + key => 'gpgkey=', + value => "$loninst/$info{$type}{gpg}", + }, {section => 'loncapa-updates-noarch', + key => 'name=', + value => $info{$type}{title}.' $releasever LON-CAPA noarch Updates', + }, {section => 'loncapa-updates-noarch', + key => 'baseurl=', + value => "$loninst/$info{$type}{path}/$release/noarch", + }, {section => 'loncapa-updates-noarch', + key => 'gpgcheck=', + value => $info{$type}{gpgchk}, + }, {section => 'loncapa-updates-noarch', + key => 'gpgkey=', + value => "$loninst/$info{$type}{gpg}", + }],$nobackup); + } elsif (($type eq 'rhes') && ($ver == 4)) { + my %rhn = ( + basearch => { + regexp => '\s*yum\s+loncapa\-updates\-basearch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/\$ARCH', + text => "yum loncapa-updates-basearch $loninst/$info{$type}{path}/$longver/".'$ARCH', + }, + noarch => { + regexp => '\s*yum\s+loncapa\-updates\-noarch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/noarch', + text => "yum loncapa-updates-noarch $loninst/$info{$type}{path}/$longver/noarch", + }, + ); + $yum_status = &update_rhn_source(\%rhn); + } + } +} elsif ($dist =~ /^(debian|ubuntu)(\d+)$/) { + my ($distname,$distver) = ($1,$2); + if ((($distname eq 'ubuntu') && ($distver > 20)) || + (($distname eq 'debian') && ($distver >= 10))) { + $loninst = 'https://install.loncapa.org'; + $loninst_re = 'https://install\.loncapa\.org'; + } + my %apt_get_source = ( + debian5 => { + regexp => '\s*deb\s+'.$loninst_re.'/debian/?\s+lenny\s+main', + text => "deb $loninst/debian lenny main", + }, + debian6 => { + regexp => '\s*deb\s+'.$loninst_re.'/debian/?\s+squeeze\s+main', + text => "deb $loninst/debian squeeze main", + }, + debian10 => { + regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/debian/?\s+buster\s+main', + text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/debian buster main", + }, + debian11 => { + regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/debian/?\s+bullseye\s+main', + text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/debian bullseye main", + }, + debian12 => { + regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/debian/?\s+bookworm\s+main', + text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/debian bookworm main", + }, + + ubuntu6 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+dapper\s+main', + text => "deb $loninst/ubuntu dapper main", + }, + ubuntu8 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+hardy\s+main', + text => "deb $loninst/ubuntu hardy main", + }, + ubuntu10 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+lucid\s+main', + text => "deb $loninst/ubuntu lucid main", + }, + ubuntu12 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+precise\s+main', + text => "deb $loninst/ubuntu precise main", + }, + ubuntu14 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+trusty\s+main', + text => "deb $loninst/ubuntu trusty main", + }, + ubuntu16 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+xenial\s+main', + text => "deb $loninst/ubuntu xenial main", + }, + ubuntu18 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+bionic\s+main', + text => "deb $loninst/ubuntu bionic main", + }, + ubuntu20 => { + regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+focal\s+main', + text => "deb $loninst/ubuntu focal main", + }, + ubuntu22 => { + regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/ubuntu/?\s+jammy\s+main', + text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/ubuntu jammy main", + }, + ubuntu24 => { + regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/ubuntu/?\s+noble\s+main', + text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/ubuntu noble main", + }, + ); + my $apt_status; + if (defined($apt_get_source{$dist})) { + $apt_status = &update_apt_source($distname,$distver,$apt_get_source{$dist}); + } +} + +my $mysqlfile = '/etc/my.cnf'; +my $mysqlconf = [{section =>'mysqld', + key =>'wait_timeout=', + value =>'31536000'}]; +my $nomysqlbackup; +if ($dist =~ /^ubuntu(\d+)$/) { + my $version = $1; + $mysqlfile = '/etc/mysql/my.cnf'; + if ($version > 14) { + $nomysqlbackup = 1; + $mysqlfile = '/etc/mysql/mysql.conf.d/mysqld.cnf'; + if ($version < 20) { + push(@{$mysqlconf}, + {section =>'mysqld', + key =>'sql_mode=', + value =>'"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"'}); + } else { + push(@{$mysqlconf}, + {section =>'mysqld', + key =>'sql_mode=', + value =>'"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"'}); + } + } +} elsif ($dist =~ /^debian(\d+)$/) { + my $version = $1; + if ($version >= 10) { + $mysqlfile = '/etc/mysql/mariadb.conf.d/50-server.cnf'; + $nomysqlbackup = 1; + } +} + +my $mysql_global_status = &update_file($mysqlfile,$mysqlconf,$nomysqlbackup); + +my $local_my_cnf = '/home/www/.my.cnf'; +if (! -e $local_my_cnf) { + # Create a file so we can do something with it... + system("touch $local_my_cnf"); +} +my $mysql_www_status = + &update_file($local_my_cnf, + [{section =>'client', + key =>'user=', + value =>'www',}, + {section =>'client', + key =>'password=', + value =>$loncapa_config->{'lonSqlAccess'}},]); + +my $needs_inputrc_check; +if ($dist =~ /^debian(\d+)$/) { + if ($1 >= 12) { + $needs_inputrc_check = 1; + } +} elsif ($dist =~ /^ubuntu(\d+)$/) { + if ($1 >= 22) { + $needs_inputrc_check = 1; + } +} elsif ($dist =~ /^(?:rhes|oracle|alma|rocky|centos)(\d+)(?:|\-stream)$/) { + if ($1 >= 9) { + $needs_inputrc_check = 1; + } +} elsif ($dist =~ /^fedora(\d+)$/) { + if ($1 >= 34) { + $needs_inputrc_check = 1; + } +} + +if ($needs_inputrc_check) { + my $bash_www_cnf = '/home/www/.inputrc'; + if (!-e $bash_www_cnf) { + system("touch $bash_www_cnf"); + if (open(my $fh,'>',$bash_www_cnf)) { + print $fh <<'END'; +$if R + set enable-bracketed-paste off +$endif + +$if maxima + set enable-bracketed-paste off +$endif +END + close($fh); + } else { + warn "**** Error: could not open $bash_www_cnf to add 'set enable-bracketed-paste to off'"; + } + my $wwwuid = getpwnam('www'); + my $wwwgid = getgrnam('www'); + if ($wwwuid!=$<) { + chown($wwwuid,$wwwgid,$bash_www_cnf); + } + } else { + my (%bracketed_paste_on,%bracketed_paste_off,@preserve,$condition); + $condition = ''; + if (open(my $fh,'<',$bash_www_cnf)) { + while (my $line=<$fh>) { + chomp($line); + if ($line =~ /^\$if\s+(\w+)\s*$/) { + if ($1 eq 'R') { + $condition = 'r'; + } elsif ($1 eq 'maxima') { + $condition = 'maxima'; + } else { + $condition = 'other'; + } + } elsif ($line =~ /^\$endif\s*$/) { + $condition = ''; + } + if ($line =~ /^\s*set\s+enable\-bracketed\-paste\s+(off|on)\s*$/) { + if ($1 eq 'off') { + if ($condition ne '') { + $bracketed_paste_off{$condition} = 1; + } else { + $bracketed_paste_off{all} = 1; + } + push(@preserve,$line); + } else { + if ($condition ne '') { + $bracketed_paste_on{$condition} = 1; + if (($condition eq 'r') || ($condition eq 'maxima')) { + push(@preserve,' set enable-bracketed-paste off'); + } else { + push(@preserve,$line); + } + } else { + $bracketed_paste_on{all} = 1; + push(@preserve,$line); + } + } + } else { + push(@preserve,$line); + } + } + close($fh); + } + if (($bracketed_paste_on{r} || $bracketed_paste_on{maxima}) || + (!exists($bracketed_paste_off{r}) && !exists($bracketed_paste_on{r}) && + !exists($bracketed_paste_off{maxima}) && !exists($bracketed_paste_on{maxima}))) { + if (open(my $fh,'>',$bash_www_cnf)) { + if (@preserve) { + foreach my $entry (@preserve) { + print $fh "$entry\n"; + } + if (!exists($bracketed_paste_off{r}) && !exists($bracketed_paste_on{r})) { +print $fh <<'END'; +$if R + set enable-bracketed-paste off +$endif +END + } + if (!exists($bracketed_paste_off{r}) && !exists($bracketed_paste_on{r})) { +print $fh <<'END'; +$if maxima + set enable-bracketed-paste off +$endif +END + } + } else { +print $fh <<'END'; +$if R + set enable-bracketed-paste off +$endif + +$if maxima + set enable-bracketed-paste off +$endif +END + } + close($fh); + } else { + warn "**** Error: could not open $bash_www_cnf to add 'set enable-bracketed-paste to off'"; + } + } + } +} -exit; +my $exitvalue = 0; +if ($mysql_global_status) { $exitvalue = 1; } +exit $exitvalue; ################################################################# ################################################################# @@ -83,29 +504,53 @@ exit; =over 4 +=item &update_file() + +Calls &parse_config_file for a file and then sends the +retrieved data to &modify_config_file, and checks if +modificatione were made. + +Inputs: filename, newdata (reference to an array of hashed), + nobackup 1, if no backup of existing file (.backup + appended to filename) should be made. + +Output: 0 or 1; o if no modifications exist (and hence no file +needed to be saved, or 1 if modifications made, and call to +&write_config_file to save file, or if filename does not exist. + +=back + =cut ################################################################# ################################################################# + + sub update_file { - my ($file,$newdata) = @_; + my ($file,$newdata,$nobackup) = @_; return 1 if (! -e $file); - my $backup = $file.'.backup'; - if (! copy($file,$backup)) { - warn "Error: Unable to make backup of $file"; - return 0; + unless ($nobackup) { + my $backup = $file.'.backup'; + if (! copy($file,$backup)) { + warn "**** Error: Unable to make backup of $file"; + return 0; + } } my ($filedata) = &parse_config_file($file); - if (! ref($filedata)) { warn "Error: $filedata"; return 0;} + if (! ref($filedata)) { warn "**** Error: $filedata"; return 0;} + my $modified = 0; foreach my $data (@$newdata) { my $section = $data->{'section'}; my $key = $data->{'key'}; my $value = $data->{'value'}; - &modify_config_file($filedata,$section,$key,$value) + my $result = &modify_config_file($filedata,$section,$key,$value); + if ($result) { $modified = 1; } } - my $result = &write_config_file($file,$filedata); - if (defined($result)) { warn 'Error:'.$result; return 0; } - return 1; + if ($modified) { + my $result = &write_config_file($file,$filedata); + if (defined($result)) { warn 'Error:'.$result; return 0; } + } + return $modified; } ################################################################# @@ -113,7 +558,9 @@ sub update_file { =pod -=item &parse_config_file +=over 4 + +=item &parse_config_file() Read a configuration file in and parse it into an internal data structure. @@ -121,6 +568,8 @@ Input: filename Output: array ref $filedata OR scalar error message +=back + =cut ################################################################# @@ -138,6 +587,7 @@ sub parse_config_file { my $section_id = $1; push(@Structure,'__section__'.$section_id); while ($line = shift(@Input)) { + chomp($line); if ($line =~ /^\[([^\]]*)\]/) { unshift(@Input,$line); last; @@ -158,7 +608,9 @@ sub parse_config_file { =pod -=item +=over 4 + +=item &write_config_file() Write a configuration file out based on the internal data structure returned by &parse_config_file @@ -167,6 +619,8 @@ Inputs: filename, $filedata (the return Returns: undef on success, scalar error message on failure. +=back + =cut ################################################################# @@ -177,7 +631,7 @@ sub write_config_file { if (! defined($structure) || ! ref($structure)) { return 'Bad subroutine inputs'; } - open(OUTPUT,'>'.$file) || return('Unable to open '.$file.' for writing'); + open(OUTPUT,'>',$file) || return('Unable to open '.$file.' for writing'); for (my $i=0;$i[$i]; chomp($line); @@ -208,7 +662,9 @@ sub write_config_file { =pod -=item &modify_config_file +=over 4 + +=item &modify_config_file() Modifies the internal data structure of a configuration file to include new sections and/or new configuration directives. @@ -220,12 +676,17 @@ value prepended). $newkey: A line which matches this will be replaced with $newkey.$newvalue $newvalue: The new value to be placed with the new key. +Returns: 0 or 1, indicating if the file was modified(1) or not(0). + +=back + =cut ################################################################# ################################################################# sub modify_config_file { my ($filedata,$section,$newkey,$newvalue)=@_; + my $modified = 0; # returned value - set to true if the file is modified my ($structure,$sections) = @$filedata; if (! defined($newvalue)) { $newvalue = ''; @@ -247,9 +708,11 @@ sub modify_config_file { # Put the item in or update it. my $key_is_new = 1; for (my $i=0;$i[$i] =~/^$newkey/) { - $target->[$i]=$newline; + if ($target->[$i] ne $newline) { + $target->[$i]=$newline; + $modified = 1; + } $key_is_new = 0; last; } @@ -261,23 +724,162 @@ sub modify_config_file { # No need to put things after a blank line. if (defined($target->[-1]) && $target->[-1] =~ /^\s*$/) { $target->[-1] = $newline; + $modified = 1; } else { push(@$target,$newline); + $modified = 1; } } } - return ($filedata); + return $modified; } +################################################################# +################################################################# + +=pod + +=over 4 + +=item &update_rhn_source() + +Modifies the Red Hat 4 sources file which includes repositories used by up2date + +Inputs: +$rhn_items - a reference to hash of a hash containing the regular expression +to test for, and the text string to append to the file, if an entry for the +LON-CAPA RHEL repository is missing for two cases: + +(a) basearch +(b) noarch + +Returns: 0 or 1, indicating if the file was modified(1) or not(0). + +=back + +=cut + +################################################################# +################################################################# +sub update_rhn_source { + my ($rhn_items) = @_; + return 0 if (ref($rhn_items) ne 'HASH'); + return 0 if ((ref($rhn_items->{basearch}) ne 'HASH') || (ref($rhn_items->{noarch}) ne 'HASH')); + my $file = '/etc/sysconfig/rhn/sources'; + return 0 if (! -e $file); + my $backup = $file.'.backup'; + if (! copy($file,$backup)) { + warn "**** Error: Unable to make backup of $file"; + return 0; + } + my $result = 0; + my $fh; + if (open($fh,'<',$file)) { + my $total = 0; + my %found; + foreach my $item (keys(%{$rhn_items})) { + $found{$item} = 0; + } + while(<$fh>) { + foreach my $item (keys(%{$rhn_items})) { + if (ref($rhn_items->{$item}) eq 'HASH') { + my $pattern = $rhn_items->{$item}->{regexp}; + if ($pattern ne '') { + if (m{^$pattern}) { + $found{$item} = 1; + $total ++; + } + } + } + } + last if $total == 2; + } + close($fh); + if ($total < 2) { + if (open($fh,'>>',$file)) { + foreach my $item (keys(%{$rhn_items})) { + unless ($found{$item}) { + if (ref($rhn_items->{$item}) eq 'HASH') { + if ($rhn_items->{$item}->{text} ne '') { + print $fh "\n".$rhn_items->{$item}->{text}."\n"; + $result = 1; + } + } + } + } + close($fh); + } + } + } + return $result; +} ################################################################# ################################################################# =pod +=over 4 + +=item &update_apt_source() + +Modifies either the sources.list or sources.list.d/loncapa.list +file which include repositories used by apt-get. + +Inputs: +$distname - distro (without version): debian or ubuntu +$distver - distro version, e.g., 12 or 24 +$deb_row - a reference to a hash containing the regular expression +to test for, and the text string to append to the file, if an entry +for the LON-CAPA Debian/ or Ubuntu repository is missing. + +Returns: 0 or 1, indicating if the file was modified(1) or not(0). + =back =cut ################################################################# ################################################################# +sub update_apt_source { + my ($distname,$distver,$deb_row) = @_; + return 0 if (ref($deb_row) ne 'HASH'); + return 0 if (($deb_row->{regexp} eq '') || ($deb_row->{text} eq '')); + my $file = '/etc/apt/sources.list'; + my $nobackup; + if ((($distname eq 'ubuntu') && ($distver > 20)) || + (($distname eq 'debian') && ($distver >= 10))) { + $file = '/etc/apt/sources.list.d/loncapa.list'; + $nobackup = 1; + } + return 0 if (! -e $file); + unless ($nobackup) { + my $backup = $file.'.backup'; + if (! copy($file,$backup)) { + warn "**** Error: Unable to make backup of $file"; + return 0; + } + } + my $result = 0; + my $fh; + if (open($fh,'<',$file)) { + my $found = 0; + my $pattern = $deb_row->{regexp}; + while(<$fh>) { + if (m{^$pattern}) { + $found = 1; + last; + } + } + close($fh); + if (!$found) { + if (open($fh,'>>',$file)) { + print $fh "\n".$deb_row->{text}."\n"; + close($fh); + $result = 1; + } + } + } + return $result; +} +