File:  [LON-CAPA] / loncom / debugging_tools / modify_config_files.pl
Revision 1.23: download - view: text, annotated - select for diffs
Tue Dec 21 15:43:57 2021 UTC (2 years, 4 months ago) by raeburn
Branches: MAIN
CVS tags: version_2_12_X, version_2_11_X, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, HEAD
- Add quotes for hash key containing a -

    1: #!/usr/bin/perl -w
    2: #
    3: # The LearningOnline Network
    4: #
    5: # $Id: modify_config_files.pl,v 1.23 2021/12/21 15:43:57 raeburn Exp $
    6: #
    7: # Copyright Michigan State University Board of Trustees
    8: #
    9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   10: #
   11: # LON-CAPA is free software; you can redistribute it and/or modify
   12: # it under the terms of the GNU General Public License as published by
   13: # the Free Software Foundation; either version 2 of the License, or
   14: # (at your option) any later version.
   15: #
   16: # LON-CAPA is distributed in the hope that it will be useful,
   17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19: # GNU General Public License for more details.
   20: #
   21: # You should have received a copy of the GNU General Public License
   22: # along with LON-CAPA; if not, write to the Free Software
   23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   24: #
   25: # /home/httpd/html/adm/gpl.txt
   26: #
   27: # http://www.lon-capa.org/
   28: #
   29: ###
   30: 
   31: =pod
   32: 
   33: =head1 NAME
   34: 
   35: B<modify_config_files.pl>
   36: 
   37: =head1 SYNOPSIS
   38: 
   39: This script modifies /etc/my.cnf and one of: /etc/yum.conf 
   40: (for CentOS/Scientific Linux/RHEL >=5 and <8), /etc/apt/sources.list
   41: (for Debian/Ubuntu), /etc/sysconfig/rhn/sources (for RHEL4),
   42: and /etc/yum.repos.d/loncapa.repo (Fedora >= 21; Oracle Linux; 
   43: CentOS/RHEL >= 8).
   44: 
   45: =head1 DESCRIPTION
   46: 
   47: This script modifies /etc/my.cnf, /etc/yum.conf, /etc/yum.repos.d/loncapa.repo,
   48: /etc/apt/sources, or /etc/sysconfig/rhn/sources to ensure certain
   49: parameters are set properly.
   50: 
   51: The LON-CAPA yum repositories are added to /etc/yum.conf, 
   52: /etc/yum.repos.d/loncapa.repo, /etc/sysconfig/rhn/sources
   53: and the LON-CAPA apt repositories are added to 
   54: /etc/apt/sources.list.
   55: 
   56: The /etc/my.cnf file is modified to set the wait_timeout to 1 year.  Backup
   57: copies of each file are made in /etc, /etc/apt, and /etc/sysconfig/rhn, as 
   58: appropriate.
   59: 
   60: =cut
   61: 
   62: use strict;
   63: use File::Copy;
   64: use lib '/home/httpd/lib/perl/';
   65: use LONCAPA::Configuration;
   66: my $loncapa_config=LONCAPA::Configuration::read_conf('loncapa.conf');
   67: 
   68: open(DSH,"$$loncapa_config{'lonDaemons'}/distprobe |");
   69: my $dist = <DSH>;
   70: chomp($dist);
   71: close(DSH);
   72: 
   73: my $yum_status;
   74: my $loninst = 'http://install.loncapa.org';
   75: my $loninst_re = 'http://install\.loncapa\.org';
   76: if ($dist =~ /^fedora(\d+)$/) {
   77:     my $file = '/etc/yum.conf';
   78:     my $ver = $1;
   79:     my $gpgchk = '0';
   80:     my $gpg = "$loninst/versions/fedora/RPM-GPG-KEY-loncapa"; 
   81:     my $nobackup;
   82:     if ($ver > 6) {
   83:         $gpgchk = '1';
   84:     }
   85:     if ($ver >= 21) {
   86:         $file = '/etc/yum.repos.d/loncapa.repo';
   87:         $nobackup = 1;
   88:     }
   89:     $yum_status =  
   90:         &update_file($file,
   91:              [{section => 'loncapa-updates-basearch',
   92:                key     => 'name=',
   93:                value   => 'Fedora Core $releasever LON-CAPA $basearch Updates',
   94:            }, {section => 'loncapa-updates-basearch',
   95:                key     => 'baseurl=',
   96:                value   => $loninst.'/fedora/linux/loncapa/$releasever/$basearch',
   97:            }, {section => 'loncapa-updates-basearch',
   98:                key     => 'gpgcheck=',
   99:                value   =>  $gpgchk,
  100:            }, {section => 'loncapa-updates-basearch',
  101:                key     => 'gpgkey=',
  102:                value   => $gpg,
  103:            }, {section => 'loncapa-updates-noarch',
  104:                key     => 'name=',
  105:                value   => 'Fedora Core $releasever LON-CAPA noarch Updates',
  106:            }, {section => 'loncapa-updates-noarch',
  107:                key     => 'baseurl=',
  108:                value   => $loninst.'/fedora/linux/loncapa/$releasever/noarch',
  109:            }, {section => 'loncapa-updates-noarch',
  110:                key     => 'gpgcheck=',
  111:                value   => $gpgchk,
  112:            }, {section => 'loncapa-updates-noarch',
  113:                key     => 'gpgkey=',
  114:                value   => $gpg,
  115:            }],$nobackup);
  116: } elsif ($dist =~ /^(rhes|centos|scientific|oracle|rocky|alma)(\d+)(|\-stream)$/) {
  117:     my $type = $1;
  118:     my $ver = $2;
  119:     my $stream = $3;
  120:     my $longver = $ver;
  121:     my $nobackup;
  122:     if ($type eq 'rhes') {
  123:         if ($ver == 4) {
  124:             $longver = '4ES';
  125:         } elsif ($ver == 5) {
  126:             $longver = '5Server';
  127:         }
  128:     } elsif ($type eq 'centos') {
  129:         $type .= $stream;
  130:     }
  131:     my %info = (
  132:                  rhes => {
  133:                            title => 'RHEL',
  134:                            path => 'redhat/linux/enterprise/loncapa',
  135:                            gpg => 'versions/redhat/RPM-GPG-KEY-loncapa',
  136:                            gpgchk => 1,
  137:                          },
  138:                  centos => {
  139:                              title => 'CentOS',
  140:                              path => 'centos/loncapa',
  141:                              gpg => 'versions/centos/RPM-GPG-KEY-loncapa',
  142:                              gpgchk => 1,
  143:                            },
  144:                  scientific => {
  145:                                  title => 'Scientific Linux',
  146:                                  path => 'scientific/loncapa',
  147:                                  gpg => 'versions/scientific/RPM-GPG-KEY-loncapa',
  148:                                  gpgchk => 1,
  149:                                },
  150:                  oracle => {
  151:                              title => 'Oracle Linux',
  152:                              path => 'oracle/loncapa',
  153:                              gpg => 'versions/oracle/RPM-GPG-KEY-loncapa',
  154:                              gpgchk => 1,
  155:                            },
  156:                  rocky => {
  157:                              title => 'Rocky Linux',
  158:                              path => 'rocky/loncapa',
  159:                              gpg => 'versions/rocky/RPM-GPG-KEY-loncapa',
  160:                              gpgchk => 1,
  161:                           },
  162:                  alma => {
  163:                              title => 'AlmaLinux',
  164:                              path => 'alma/loncapa',
  165:                              gpg => 'versions/alma/RPM-GPG-KEY-loncapa',
  166:                              gpgchk => 1,
  167:                           },
  168:                  'centos-stream' => {
  169:                                       title => 'CentOS Stream',
  170:                                       path  => 'centos/loncapa',
  171:                                       gpg => 'versions/centos/RPM-GPG-KEY-loncapa',
  172:                                       gpgchk => 1, 
  173:                                     },
  174:                );
  175:     if (ref($info{$type}) eq 'HASH') {
  176:         if ($ver > 4) {
  177:             my $file = '/etc/yum.conf';
  178:             if (($ver > 7) || ($type eq 'oracle') || ($type eq 'rocky') || 
  179:                 ($type eq 'alma') || ($type eq 'centos-stream')) {
  180:                 $file = '/etc/yum.repos.d/loncapa.repo';
  181:                 $nobackup = 1;
  182:             }
  183:             my $release = '$releasever';
  184:             if ($type eq 'centos-stream') {
  185:                 $release .= '-stream';
  186:             }
  187:             $yum_status =
  188:                 &update_file($file,
  189:                      [{section => 'loncapa-updates-basearch',
  190:                        key     => 'name=',
  191:                        value   => $info{$type}{title}.' $releasever LON-CAPA $basearch Updates',
  192:                       }, {section => "loncapa-updates-basearch",
  193:                           key     => 'baseurl=',
  194:                           value   => "$loninst/$info{$type}{path}/$release/".'$basearch',
  195:                       }, {section => 'loncapa-updates-basearch',
  196:                           key     => 'gpgcheck=',
  197:                           value   => $info{$type}{gpgchk},
  198:                       }, {section => 'loncapa-updates-basearch',
  199:                           key     => 'gpgkey=',
  200:                           value   => "$loninst/$info{$type}{gpg}",
  201:                       }, {section => 'loncapa-updates-noarch',
  202:                           key     => 'name=',
  203:                           value   => $info{$type}{title}.' $releasever LON-CAPA noarch Updates',
  204:                       }, {section => 'loncapa-updates-noarch',
  205:                           key     => 'baseurl=',
  206:                           value   => "$loninst/$info{$type}{path}/$release/noarch",
  207:                       }, {section => 'loncapa-updates-noarch',
  208:                           key     => 'gpgcheck=',
  209:                           value   => $info{$type}{gpgchk},
  210:                       }, {section => 'loncapa-updates-noarch',
  211:                           key     => 'gpgkey=',
  212:                           value   => "$loninst/$info{$type}{gpg}",
  213:                       }],$nobackup);
  214:         } elsif (($type eq 'rhes') && ($ver == 4)) {
  215:             my %rhn = (
  216:                         basearch => { 
  217:                             regexp => '\s*yum\s+loncapa\-updates\-basearch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/\$ARCH',
  218:                             text => "yum loncapa-updates-basearch $loninst/$info{$type}{path}/$longver/".'$ARCH',
  219:                                     },
  220:                         noarch =>  {
  221:                             regexp => '\s*yum\s+loncapa\-updates\-noarch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/noarch',
  222:                             text => "yum loncapa-updates-noarch $loninst/$info{$type}{path}/$longver/noarch",
  223:                                    },
  224:                       );
  225:             $yum_status = &update_rhn_source(\%rhn); 
  226:         }
  227:     }
  228: } elsif ($dist =~ /^(debian|ubuntu)\d+$/) {
  229:     my %apt_get_source = (
  230:                            debian5 => {
  231:                                         regexp => '\s*deb\s+'.$loninst_re.'/debian/?\s+lenny\s+main',
  232:                                         text   => "deb $loninst/debian lenny main",
  233:                                       },
  234:                            ubuntu6 => {
  235:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+dapper\s+main',
  236:                                         text   => "deb $loninst/ubuntu dapper main",
  237:                                       },
  238:                            ubuntu8 => {
  239:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+hardy\s+main',
  240:                                         text   => "deb $loninst/ubuntu hardy main",
  241:                                       },
  242:                            ubuntu10 => {
  243:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+lucid\s+main',
  244:                                         text   => "deb $loninst/ubuntu lucid main",
  245:                                        },
  246:                            ubuntu12 => {
  247:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+precise\s+main',
  248:                                         text   => "deb $loninst/ubuntu precise main",
  249:                                        },
  250:                            ubuntu14 => {
  251:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+trusty\s+main',
  252:                                         text   => "deb $loninst/ubuntu trusty main",
  253:                                        },
  254:                            ubuntu16 => {
  255:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+xenial\s+main',
  256:                                         text   => "deb $loninst/ubuntu xenial main",
  257:                                        },
  258:                            ubuntu18 => {
  259:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+bionic\s+main',
  260:                                         text   => "deb $loninst/ubuntu bionic main",
  261:                                        },
  262:                            ubuntu20 => {
  263:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+focal\s+main',
  264:                                         text   => "deb $loninst/ubuntu focal main",
  265:                                        },
  266:                          );
  267:     my $apt_status;
  268:     if (defined($apt_get_source{$dist})) {
  269:         $apt_status = &update_apt_source($apt_get_source{$dist},);
  270:     }
  271: }
  272: 
  273: my $mysqlfile = '/etc/my.cnf';
  274: my $mysqlconf = [{section =>'mysqld',
  275:                   key     =>'wait_timeout=',
  276:                   value   =>'31536000'}];
  277: if ($dist =~ /^ubuntu(\d+)$/) {
  278:     my $version = $1;
  279:     $mysqlfile = '/etc/mysql/my.cnf';
  280:     if ($version > 14) {
  281:         $mysqlfile = '/etc/mysql/mysql.conf.d/mysqld.cnf';
  282:         if ($version < 20) {
  283:             push(@{$mysqlconf},
  284:                  {section =>'mysqld',
  285:                   key     =>'sql_mode=',
  286:                   value   =>'"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"'});
  287:         } else {
  288:             push(@{$mysqlconf},
  289:                  {section =>'mysqld',
  290:                   key     =>'sql_mode=',
  291:                   value   =>'"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"'});
  292:         }
  293:     }
  294: }
  295: 
  296: my $mysql_global_status = &update_file($mysqlfile,$mysqlconf);
  297: 
  298: my $local_my_cnf = '/home/www/.my.cnf';
  299: if (! -e $local_my_cnf) {
  300:     # Create a file so we can do something with it...
  301:     system("touch $local_my_cnf");
  302: }
  303: my $mysql_www_status =
  304:     &update_file($local_my_cnf,
  305:              [{section =>'client',
  306:                key     =>'user=',
  307:                value   =>'www',},
  308:               {section =>'client',
  309:                key     =>'password=',
  310:                value   =>$loncapa_config->{'lonSqlAccess'}},]);
  311: 
  312: my $exitvalue = 0;
  313: 
  314: if ($mysql_global_status) { $exitvalue = 1; }
  315: 
  316: exit $exitvalue;
  317: 
  318: 
  319: sub update_file {
  320:     my ($file,$newdata,$nobackup) = @_;
  321:     return 1 if (! -e $file);
  322:     unless ($nobackup) {
  323:         my $backup = $file.'.backup';
  324:         if (! copy($file,$backup)) {
  325:             warn "**** Error: Unable to make backup of $file";
  326:             return 0;
  327:         }
  328:     }
  329:     my ($filedata) = &parse_config_file($file);
  330:     if (! ref($filedata)) { warn "**** Error: $filedata"; return 0;}
  331:     my $modified = 0;
  332:     foreach my $data (@$newdata) {
  333:         my $section = $data->{'section'};
  334:         my $key = $data->{'key'};
  335:         my $value = $data->{'value'};
  336:         my $result = &modify_config_file($filedata,$section,$key,$value);
  337:         if ($result) { $modified = 1; }
  338:     }
  339:     if ($modified) {
  340:         my $result = &write_config_file($file,$filedata);
  341:         if (defined($result)) { warn 'Error:'.$result; return 0; }
  342:     }
  343:     return $modified;
  344: }
  345: 
  346: #################################################################
  347: #################################################################
  348: 
  349: =pod
  350: 
  351: =over 4
  352: 
  353: =item &parse_config_file()
  354: 
  355: Read a configuration file in and parse it into an internal data structure.
  356: 
  357: Input: filename
  358: 
  359: Output: array ref $filedata  OR  scalar error message
  360: 
  361: =back 
  362: 
  363: =cut
  364: 
  365: #################################################################
  366: #################################################################
  367: sub parse_config_file {
  368:     my ($file) = @_;
  369:     open(INFILE,$file) || return ('Unable to open '.$file.' for reading');
  370:     my @Input = <INFILE>;
  371:     close(INFILE);
  372:     my @Structure;
  373:     my %Sections;
  374:     while (my $line = shift(@Input)) {
  375:         chomp($line);
  376:         if ($line =~ /^\[([^\]]*)\]/) {
  377:             my $section_id = $1;
  378:             push(@Structure,'__section__'.$section_id);
  379:             while ($line = shift(@Input)) {
  380:                 chomp($line);
  381:                 if ($line =~ /^\[([^\]]*)\]/) {
  382:                     unshift(@Input,$line);
  383:                     last;
  384:                 } else {
  385:                     push(@{$Sections{$section_id}},$line);
  386:                 }
  387:             }
  388:         } else {
  389:             push(@Structure,$line);
  390:         }
  391:     }
  392:     my $filedata = [\@Structure,\%Sections];
  393:     return $filedata;
  394: }
  395: 
  396: #################################################################
  397: #################################################################
  398: 
  399: =pod
  400: 
  401: =over 4
  402: 
  403: =item
  404: 
  405: Write a configuration file out based on the internal data structure returned
  406: by &parse_config_file
  407: 
  408: Inputs: filename, $filedata (the return value of &parse_config_file
  409: 
  410: Returns: undef on success, scalar error message on failure.
  411: 
  412: =back
  413: 
  414: =cut
  415: 
  416: #################################################################
  417: #################################################################
  418: sub write_config_file {
  419:     my ($file,$filedata) = @_;
  420:     my ($structure,$sections) = @$filedata;
  421:     if (! defined($structure) || ! ref($structure)) {
  422:         return 'Bad subroutine inputs';
  423:     }
  424:     open(OUTPUT,'>',$file) || return('Unable to open '.$file.' for writing');
  425:     for (my $i=0;$i<scalar(@$structure);$i++) {
  426:         my $line = $structure->[$i];
  427:         chomp($line);
  428:         if ($line =~ /^__section__(.*)$/) {
  429:             my $section_id = $1;
  430:             print OUTPUT ('['.$section_id.']'.$/);
  431:             foreach my $section_line (@{$sections->{$section_id}}) {
  432:                 chomp($section_line);
  433:                 print OUTPUT $section_line.$/;
  434:             }
  435:             # Deal with blank lines
  436:             if ($sections->{$section_id}->[-1] =~ /^\s*$/) {
  437:                 # No need to output a blank line at the end if there is one 
  438:                 # already
  439:             } else {
  440:                 print OUTPUT $/;
  441:             }
  442:         } else {
  443:             print OUTPUT $line.$/;
  444:         }
  445:     }
  446:     close OUTPUT;
  447:     return undef;
  448: }
  449: 
  450: #################################################################
  451: #################################################################
  452: 
  453: =pod
  454: 
  455: =over 4
  456: 
  457: =item &modify_config_file()
  458: 
  459: Modifies the internal data structure of a configuration file to include new
  460: sections and/or new configuration directives.
  461: 
  462: Inputs: $filedata (see &parse_config_file
  463: $section, the [section] the new entry is to reside in.  A value of undef will
  464: cause the "outer" section (as in yum.conf) to be updated (or have the new
  465: value prepended).
  466: $newkey: A line which matches this will be replaced with $newkey.$newvalue
  467: $newvalue: The new value to be placed with the new key.
  468: 
  469: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
  470: 
  471: =back 
  472: 
  473: =cut
  474: 
  475: #################################################################
  476: #################################################################
  477: sub modify_config_file {
  478:     my ($filedata,$section,$newkey,$newvalue)=@_;
  479:     my $modified = 0;    # returned value - set to true if the file is modified
  480:     my ($structure,$sections) = @$filedata;
  481:     if (! defined($newvalue)) {
  482:         $newvalue = '';
  483:     }
  484:     my $newline = $newkey.$newvalue;
  485:     #
  486:     # Determine which array ref gets the item
  487:     my $target;
  488:     if (defined($section)) {
  489:         if (! exists($sections->{$section})) {
  490:             push(@$structure,'__section__'.$section);
  491:             $sections->{$section}=[];
  492:         }
  493:         $target = $sections->{$section};
  494:     } else {
  495:         $target = $structure;
  496:     }
  497:     #
  498:     # Put the item in or update it.
  499:     my $key_is_new = 1;
  500:     for (my $i=0;$i<scalar(@$target);$i++) {
  501:         if ($target->[$i] =~/^$newkey/) {
  502:             if ($target->[$i] ne $newline) {
  503:                 $target->[$i]=$newline;
  504:                 $modified = 1;
  505:             }
  506:             $key_is_new = 0;
  507:             last;
  508:         }
  509:     }
  510:     if ($key_is_new) {
  511:         if (! defined($section)) {
  512:             unshift(@$target,$newline);
  513:         } else {
  514:             # No need to put things after a blank line.
  515:             if (defined($target->[-1]) && $target->[-1] =~ /^\s*$/) {
  516:                 $target->[-1] = $newline;
  517:                 $modified = 1;
  518:             } else {
  519:                 push(@$target,$newline);
  520:                 $modified = 1;
  521:             }
  522:         }
  523:     }
  524:     return $modified;
  525: }
  526: 
  527: #################################################################
  528: #################################################################
  529: 
  530: =pod
  531: 
  532: =over 4
  533: 
  534: =item &update_rhn_source()
  535: 
  536: Modifies the Red Hat 4 sources file which includes repositories used by up2date 
  537: 
  538: Inputs: 
  539: $rhn_items - a reference to hash of a hash containing the regular expression
  540: to test for, and the text string to append to the file, if an entry for the 
  541: LON-CAPA RHEL repository is missing for two cases:
  542: 
  543: (a) basearch
  544: (b) noarch 
  545: 
  546: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
  547: 
  548: =back
  549: 
  550: =cut
  551: 
  552: #################################################################
  553: #################################################################
  554: sub update_rhn_source {
  555:     my ($rhn_items) = @_;
  556:     return 0 if (ref($rhn_items) ne 'HASH');
  557:     return 0 if ((ref($rhn_items->{basearch}) ne 'HASH') || (ref($rhn_items->{noarch}) ne 'HASH'));
  558:     my $file = '/etc/sysconfig/rhn/sources';
  559:     return 0 if (! -e $file);
  560:     my $backup = $file.'.backup';
  561:     if (! copy($file,$backup)) {
  562:         warn "**** Error: Unable to make backup of $file";
  563:         return 0;
  564:     }
  565:     my $result = 0;
  566:     my $fh;
  567:     if (open($fh,'<',$file)) {
  568:         my $total = 0;
  569:         my %found;
  570:         foreach my $item (keys(%{$rhn_items})) {
  571:             $found{$item} = 0;
  572:         }
  573:         while(<$fh>) {
  574:             foreach my $item (keys(%{$rhn_items})) {
  575:                 if (ref($rhn_items->{$item}) eq 'HASH') {
  576:                     my $pattern = $rhn_items->{$item}->{regexp};
  577:                     if ($pattern ne '') { 
  578:                         if (m{^$pattern}) {
  579:                             $found{$item} = 1;
  580:                             $total ++;
  581:                         }
  582:                     }
  583:                 }
  584:             }
  585:             last if $total == 2;
  586:         }
  587:         close($fh);
  588:         if ($total < 2) {
  589:             if (open($fh,'>>',$file)) {
  590:                 foreach my $item (keys(%{$rhn_items})) {
  591:                     unless ($found{$item}) {
  592:                         if (ref($rhn_items->{$item}) eq 'HASH') {
  593:                             if ($rhn_items->{$item}->{text} ne '') {
  594:                                 print $fh "\n".$rhn_items->{$item}->{text}."\n";
  595:                                 $result = 1;
  596:                             }
  597:                         }
  598:                     }
  599:                 }
  600:                 close($fh);
  601:             }
  602:         }
  603:     }
  604:     return $result;
  605: }
  606: 
  607: #################################################################
  608: #################################################################
  609: 
  610: =pod
  611: 
  612: =over 4
  613: 
  614: =item &update_apt_source()
  615: 
  616: Modifies the source.list file which includes repositories used by apt-get
  617: 
  618: Inputs:
  619: $deb_row - a reference to containing the regular expression
  620: to test for, and the text string to append to the file, if an entry for the
  621: LON-CAPA Debian/ or Ubuntu repository is missing.
  622: 
  623: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
  624: 
  625: =back
  626: 
  627: =cut
  628: 
  629: #################################################################
  630: #################################################################
  631: sub update_apt_source {
  632:     my ($deb_row) = @_;
  633:     return 0 if (ref($deb_row) ne 'HASH');
  634:     return 0 if (($deb_row->{regexp} eq '') || ($deb_row->{text} eq ''));
  635:     my $file = '/etc/apt/sources.list';
  636:     return 0 if (! -e $file);
  637:     my $backup = $file.'.backup';
  638:     if (! copy($file,$backup)) {
  639:         warn "**** Error: Unable to make backup of $file";
  640:         return 0;
  641:     }
  642:     my $result = 0;
  643:     my $fh;
  644:     if (open($fh,'<',$file)) {
  645:         my $found = 0;
  646:         my $pattern = $deb_row->{regexp};
  647:         while(<$fh>) {
  648:             if (m{^$pattern}) {
  649:                 $found = 1;
  650:                 last;
  651:             }
  652:         }
  653:         close($fh);
  654:         if (!$found) {
  655:             if (open($fh,'>>',$file)) {
  656:                 print $fh "\n".$deb_row->{text}."\n";
  657:                 close($fh);
  658:                 $result = 1;
  659:             }
  660:         }
  661:     }
  662:     return $result;
  663: }
  664: 

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