Annotation of loncom/debugging_tools/modify_config_files.pl, revision 1.24
1.1 matthew 1: #!/usr/bin/perl -w
2: #
3: # The LearningOnline Network
4: #
1.24 ! raeburn 5: # $Id: modify_config_files.pl,v 1.23 2021/12/21 15:43:57 raeburn Exp $
1.1 matthew 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:
1.24 ! raeburn 39: This script modifies local MySQL configuration file(s), which will be:
! 40: /home/www/.my.cnf and, depending on distro/version also one of:
! 41: /etc/my.cnf, /etc/mysql/my.cnf, /etc/mysql/mysql.conf.d/mysqld.cnf,
! 42: or /etc/mysql/mariadb.conf.d/50-server.cnf, and also the file used to
! 43: store information about the LON-CAPA package repositories located at
! 44: install.loncapa.org. which provide rpm or deb packages created for the
! 45: Linux distro/version being used. The file to modify will be one of:
! 46: /etc/yum.conf (for CentOS/Scientific Linux/RHEL >=5 and <8),
! 47: /etc/apt/sources.list (for Debian < 10 and Ubuntu < 22), or
! 48: /etc/apt/sources.list.d/loncapa.list (for Debian >= 10 and Ubuntu > 20),
! 49: /etc/sysconfig/rhn/sources (for RHEL4), or /etc/yum.repos.d/loncapa.repo
! 50: (for Fedora >= 21; Oracle Linux; AlmaLinux; RockyLinux; CentOS/RHEL >= 8).
1.1 matthew 51:
52: =head1 DESCRIPTION
53:
1.24 ! raeburn 54: This script will modify /etc/my.cnf, /etc/mysql/my.cnf,
! 55: /etc/mysql/mysql.conf.d/mysqld.cnf, or
! 56: /etc/mysql/mariadb.conf.d/50-server.cnf,
! 57: and /etc/yum.conf, /etc/yum.repos.d/loncapa.repo,
! 58: /etc/apt/sources.list, /etc/apt/sources.list.d/loncapa.list or
! 59: /etc/sysconfig/rhn/sources to ensure certain parameters are set properly.
1.13 raeburn 60:
61: The LON-CAPA yum repositories are added to /etc/yum.conf,
1.24 ! raeburn 62: /etc/yum.repos.d/loncapa.repo, or /etc/sysconfig/rhn/sources
1.13 raeburn 63: and the LON-CAPA apt repositories are added to
1.24 ! raeburn 64: /etc/apt/sources.list or /etc/apt/sources.list.d/loncapa.list.
1.9 raeburn 65:
1.24 ! raeburn 66: The /etc/my.cnf, /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf
! 67: or /etc/mysql/mariadb.conf.d/50-server.cnf file is modified to set the
! 68: wait_timeout to 1 year. Backup copies of each file are made in
! 69: /etc, /etc/apt, and /etc/sysconfig/rhn, as appropriate.
1.1 matthew 70:
71: =cut
72:
73: use strict;
74: use File::Copy;
1.3 matthew 75: use lib '/home/httpd/lib/perl/';
76: use LONCAPA::Configuration;
77: my $loncapa_config=LONCAPA::Configuration::read_conf('loncapa.conf');
1.1 matthew 78:
1.6 raeburn 79: open(DSH,"$$loncapa_config{'lonDaemons'}/distprobe |");
80: my $dist = <DSH>;
81: chomp($dist);
82: close(DSH);
83:
84: my $yum_status;
1.9 raeburn 85: my $loninst = 'http://install.loncapa.org';
86: my $loninst_re = 'http://install\.loncapa\.org';
87: if ($dist =~ /^fedora(\d+)$/) {
1.13 raeburn 88: my $file = '/etc/yum.conf';
1.9 raeburn 89: my $ver = $1;
1.10 raeburn 90: my $gpgchk = '0';
1.9 raeburn 91: my $gpg = "$loninst/versions/fedora/RPM-GPG-KEY-loncapa";
1.13 raeburn 92: my $nobackup;
1.9 raeburn 93: if ($ver > 6) {
1.10 raeburn 94: $gpgchk = '1';
1.9 raeburn 95: }
1.13 raeburn 96: if ($ver >= 21) {
97: $file = '/etc/yum.repos.d/loncapa.repo';
98: $nobackup = 1;
99: }
1.6 raeburn 100: $yum_status =
1.13 raeburn 101: &update_file($file,
1.10 raeburn 102: [{section => 'loncapa-updates-basearch',
1.1 matthew 103: key => 'name=',
1.6 raeburn 104: value => 'Fedora Core $releasever LON-CAPA $basearch Updates',
1.10 raeburn 105: }, {section => 'loncapa-updates-basearch',
1.1 matthew 106: key => 'baseurl=',
1.9 raeburn 107: value => $loninst.'/fedora/linux/loncapa/$releasever/$basearch',
1.10 raeburn 108: }, {section => 'loncapa-updates-basearch',
1.5 matthew 109: key => 'gpgcheck=',
1.9 raeburn 110: value => $gpgchk,
1.10 raeburn 111: }, {section => 'loncapa-updates-basearch',
1.13 raeburn 112: key => 'gpgkey=',
1.9 raeburn 113: value => $gpg,
1.1 matthew 114: }, {section => 'loncapa-updates-noarch',
115: key => 'name=',
116: value => 'Fedora Core $releasever LON-CAPA noarch Updates',
117: }, {section => 'loncapa-updates-noarch',
118: key => 'baseurl=',
1.9 raeburn 119: value => $loninst.'/fedora/linux/loncapa/$releasever/noarch',
1.5 matthew 120: }, {section => 'loncapa-updates-noarch',
121: key => 'gpgcheck=',
1.9 raeburn 122: value => $gpgchk,
123: }, {section => 'loncapa-updates-noarch',
1.13 raeburn 124: key => 'gpgkey=',
1.9 raeburn 125: value => $gpg,
1.13 raeburn 126: }],$nobackup);
1.22 raeburn 127: } elsif ($dist =~ /^(rhes|centos|scientific|oracle|rocky|alma)(\d+)(|\-stream)$/) {
1.9 raeburn 128: my $type = $1;
129: my $ver = $2;
1.22 raeburn 130: my $stream = $3;
1.9 raeburn 131: my $longver = $ver;
1.16 raeburn 132: my $nobackup;
1.9 raeburn 133: if ($type eq 'rhes') {
134: if ($ver == 4) {
135: $longver = '4ES';
136: } elsif ($ver == 5) {
137: $longver = '5Server';
138: }
1.22 raeburn 139: } elsif ($type eq 'centos') {
140: $type .= $stream;
1.9 raeburn 141: }
142: my %info = (
143: rhes => {
144: title => 'RHEL',
145: path => 'redhat/linux/enterprise/loncapa',
146: gpg => 'versions/redhat/RPM-GPG-KEY-loncapa',
147: gpgchk => 1,
148: },
149: centos => {
150: title => 'CentOS',
151: path => 'centos/loncapa',
152: gpg => 'versions/centos/RPM-GPG-KEY-loncapa',
153: gpgchk => 1,
154: },
155: scientific => {
156: title => 'Scientific Linux',
157: path => 'scientific/loncapa',
158: gpg => 'versions/scientific/RPM-GPG-KEY-loncapa',
159: gpgchk => 1,
160: },
1.15 raeburn 161: oracle => {
162: title => 'Oracle Linux',
163: path => 'oracle/loncapa',
164: gpg => 'versions/oracle/RPM-GPG-KEY-loncapa',
165: gpgchk => 1,
166: },
1.21 raeburn 167: rocky => {
168: title => 'Rocky Linux',
169: path => 'rocky/loncapa',
170: gpg => 'versions/rocky/RPM-GPG-KEY-loncapa',
171: gpgchk => 1,
172: },
173: alma => {
174: title => 'AlmaLinux',
175: path => 'alma/loncapa',
176: gpg => 'versions/alma/RPM-GPG-KEY-loncapa',
177: gpgchk => 1,
178: },
1.23 raeburn 179: 'centos-stream' => {
1.22 raeburn 180: title => 'CentOS Stream',
181: path => 'centos/loncapa',
182: gpg => 'versions/centos/RPM-GPG-KEY-loncapa',
183: gpgchk => 1,
1.23 raeburn 184: },
1.9 raeburn 185: );
186: if (ref($info{$type}) eq 'HASH') {
187: if ($ver > 4) {
1.16 raeburn 188: my $file = '/etc/yum.conf';
1.22 raeburn 189: if (($ver > 7) || ($type eq 'oracle') || ($type eq 'rocky') ||
190: ($type eq 'alma') || ($type eq 'centos-stream')) {
1.16 raeburn 191: $file = '/etc/yum.repos.d/loncapa.repo';
192: $nobackup = 1;
193: }
1.22 raeburn 194: my $release = '$releasever';
195: if ($type eq 'centos-stream') {
196: $release .= '-stream';
197: }
1.9 raeburn 198: $yum_status =
1.16 raeburn 199: &update_file($file,
1.9 raeburn 200: [{section => 'loncapa-updates-basearch',
201: key => 'name=',
202: value => $info{$type}{title}.' $releasever LON-CAPA $basearch Updates',
203: }, {section => "loncapa-updates-basearch",
204: key => 'baseurl=',
1.22 raeburn 205: value => "$loninst/$info{$type}{path}/$release/".'$basearch',
1.9 raeburn 206: }, {section => 'loncapa-updates-basearch',
207: key => 'gpgcheck=',
1.11 raeburn 208: value => $info{$type}{gpgchk},
1.10 raeburn 209: }, {section => 'loncapa-updates-basearch',
1.9 raeburn 210: key => 'gpgkey=',
211: value => "$loninst/$info{$type}{gpg}",
212: }, {section => 'loncapa-updates-noarch',
213: key => 'name=',
214: value => $info{$type}{title}.' $releasever LON-CAPA noarch Updates',
215: }, {section => 'loncapa-updates-noarch',
216: key => 'baseurl=',
1.22 raeburn 217: value => "$loninst/$info{$type}{path}/$release/noarch",
1.9 raeburn 218: }, {section => 'loncapa-updates-noarch',
219: key => 'gpgcheck=',
1.11 raeburn 220: value => $info{$type}{gpgchk},
1.9 raeburn 221: }, {section => 'loncapa-updates-noarch',
222: key => 'gpgkey=',
223: value => "$loninst/$info{$type}{gpg}",
1.16 raeburn 224: }],$nobackup);
1.9 raeburn 225: } elsif (($type eq 'rhes') && ($ver == 4)) {
226: my %rhn = (
227: basearch => {
228: regexp => '\s*yum\s+loncapa\-updates\-basearch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/\$ARCH',
229: text => "yum loncapa-updates-basearch $loninst/$info{$type}{path}/$longver/".'$ARCH',
230: },
231: noarch => {
232: regexp => '\s*yum\s+loncapa\-updates\-noarch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/noarch',
233: text => "yum loncapa-updates-noarch $loninst/$info{$type}{path}/$longver/noarch",
234: },
235: );
236: $yum_status = &update_rhn_source(\%rhn);
237: }
238: }
1.24 ! raeburn 239: } elsif ($dist =~ /^(debian|ubuntu)(\d+)$/) {
! 240: my ($distname,$distver) = ($1,$2);
! 241: if ((($distname eq 'ubuntu') && ($distver > 20)) ||
! 242: (($distname eq 'debian') && ($distver >= 10))) {
! 243: $loninst = 'https://install.loncapa.org';
! 244: $loninst_re = 'https://install\.loncapa\.org';
! 245: }
1.9 raeburn 246: my %apt_get_source = (
247: debian5 => {
1.18 raeburn 248: regexp => '\s*deb\s+'.$loninst_re.'/debian/?\s+lenny\s+main',
249: text => "deb $loninst/debian lenny main",
1.9 raeburn 250: },
1.24 ! raeburn 251: debian6 => {
! 252: regexp => '\s*deb\s+'.$loninst_re.'/debian/?\s+squeeze\s+main',
! 253: text => "deb $loninst/debian squeeze main",
! 254: },
! 255: debian10 => {
! 256: regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/debian/?\s+buster\s+main',
! 257: text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/debian buster main",
! 258: },
! 259: debian11 => {
! 260: regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/debian/?\s+bullseye\s+main',
! 261: text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/debian bullseye main",
! 262: },
! 263: debian12 => {
! 264: regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/debian/?\s+bookworm\s+main',
! 265: text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/debian bookworm main",
! 266: },
! 267:
1.9 raeburn 268: ubuntu6 => {
1.18 raeburn 269: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+dapper\s+main',
270: text => "deb $loninst/ubuntu dapper main",
1.9 raeburn 271: },
272: ubuntu8 => {
1.18 raeburn 273: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+hardy\s+main',
274: text => "deb $loninst/ubuntu hardy main",
1.9 raeburn 275: },
1.14 raeburn 276: ubuntu10 => {
1.18 raeburn 277: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+lucid\s+main',
278: text => "deb $loninst/ubuntu lucid main",
1.14 raeburn 279: },
280: ubuntu12 => {
1.18 raeburn 281: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+precise\s+main',
282: text => "deb $loninst/ubuntu precise main",
1.14 raeburn 283: },
284: ubuntu14 => {
1.18 raeburn 285: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+trusty\s+main',
286: text => "deb $loninst/ubuntu trusty main",
1.14 raeburn 287: },
288: ubuntu16 => {
1.18 raeburn 289: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+xenial\s+main',
290: text => "deb $loninst/ubuntu xenial main",
1.14 raeburn 291: },
292: ubuntu18 => {
1.18 raeburn 293: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+bionic\s+main',
294: text => "deb $loninst/ubuntu bionic main",
1.14 raeburn 295: },
1.17 raeburn 296: ubuntu20 => {
1.18 raeburn 297: regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/?\s+focal\s+main',
298: text => "deb $loninst/ubuntu focal main",
1.17 raeburn 299: },
1.24 ! raeburn 300: ubuntu22 => {
! 301: regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/ubuntu/?\s+jammy\s+main',
! 302: text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/ubuntu jammy main",
! 303: },
! 304: ubuntu24 => {
! 305: regexp => '\s*deb\s+\[signed\-by=/etc/apt/keyrings/loncapa\.gpg\]\s+'.$loninst_re.'/ubuntu/?\s+noble\s+main',
! 306: text => "deb [signed-by=/etc/apt/keyrings/loncapa.gpg] $loninst/ubuntu noble main",
! 307: },
1.9 raeburn 308: );
309: my $apt_status;
310: if (defined($apt_get_source{$dist})) {
1.24 ! raeburn 311: $apt_status = &update_apt_source($distname,$distver,$apt_get_source{$dist});
1.6 raeburn 312: }
313: }
1.1 matthew 314:
1.19 raeburn 315: my $mysqlfile = '/etc/my.cnf';
1.20 raeburn 316: my $mysqlconf = [{section =>'mysqld',
317: key =>'wait_timeout=',
318: value =>'31536000'}];
1.24 ! raeburn 319: my $nomysqlbackup;
1.19 raeburn 320: if ($dist =~ /^ubuntu(\d+)$/) {
321: my $version = $1;
322: $mysqlfile = '/etc/mysql/my.cnf';
323: if ($version > 14) {
1.24 ! raeburn 324: $nomysqlbackup = 1;
1.19 raeburn 325: $mysqlfile = '/etc/mysql/mysql.conf.d/mysqld.cnf';
1.20 raeburn 326: if ($version < 20) {
327: push(@{$mysqlconf},
328: {section =>'mysqld',
329: key =>'sql_mode=',
330: value =>'"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"'});
331: } else {
332: push(@{$mysqlconf},
333: {section =>'mysqld',
334: key =>'sql_mode=',
335: value =>'"STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"'});
336: }
1.19 raeburn 337: }
1.24 ! raeburn 338: } elsif ($dist =~ /^debian(\d+)$/) {
! 339: my $version = $1;
! 340: if ($version >= 10) {
! 341: $mysqlfile = '/etc/mysql/mariadb.conf.d/50-server.cnf';
! 342: $nomysqlbackup = 1;
! 343: }
1.19 raeburn 344: }
345:
1.24 ! raeburn 346: my $mysql_global_status = &update_file($mysqlfile,$mysqlconf,$nomysqlbackup);
1.1 matthew 347:
1.3 matthew 348: my $local_my_cnf = '/home/www/.my.cnf';
349: if (! -e $local_my_cnf) {
1.4 matthew 350: # Create a file so we can do something with it...
1.3 matthew 351: system("touch $local_my_cnf");
352: }
1.4 matthew 353: my $mysql_www_status =
354: &update_file($local_my_cnf,
1.3 matthew 355: [{section =>'client',
356: key =>'user=',
357: value =>'www',},
358: {section =>'client',
359: key =>'password=',
360: value =>$loncapa_config->{'lonSqlAccess'}},]);
361:
1.4 matthew 362: my $exitvalue = 0;
363:
364: if ($mysql_global_status) { $exitvalue = 1; }
365:
366: exit $exitvalue;
1.1 matthew 367:
1.24 ! raeburn 368: #################################################################
! 369: #################################################################
! 370:
! 371: =pod
! 372:
! 373: =over 4
! 374:
! 375: =item &update_file()
! 376:
! 377: Calls &parse_config_file for a file and then sends the
! 378: retrieved data to &modify_config_file, and checks if
! 379: modificatione were made.
! 380:
! 381: Inputs: filename, newdata (reference to an array of hashed),
! 382: nobackup 1, if no backup of existing file (.backup
! 383: appended to filename) should be made.
! 384:
! 385: Output: 0 or 1; o if no modifications exist (and hence no file
! 386: needed to be saved, or 1 if modifications made, and call to
! 387: &write_config_file to save file, or if filename does not exist.
! 388:
! 389: =back
! 390:
! 391: =cut
! 392:
! 393: #################################################################
! 394: #################################################################
! 395:
1.1 matthew 396:
397: sub update_file {
1.13 raeburn 398: my ($file,$newdata,$nobackup) = @_;
1.1 matthew 399: return 1 if (! -e $file);
1.13 raeburn 400: unless ($nobackup) {
401: my $backup = $file.'.backup';
402: if (! copy($file,$backup)) {
403: warn "**** Error: Unable to make backup of $file";
404: return 0;
405: }
1.1 matthew 406: }
407: my ($filedata) = &parse_config_file($file);
1.4 matthew 408: if (! ref($filedata)) { warn "**** Error: $filedata"; return 0;}
409: my $modified = 0;
1.1 matthew 410: foreach my $data (@$newdata) {
411: my $section = $data->{'section'};
412: my $key = $data->{'key'};
413: my $value = $data->{'value'};
1.4 matthew 414: my $result = &modify_config_file($filedata,$section,$key,$value);
415: if ($result) { $modified = 1; }
416: }
417: if ($modified) {
418: my $result = &write_config_file($file,$filedata);
419: if (defined($result)) { warn 'Error:'.$result; return 0; }
1.1 matthew 420: }
1.4 matthew 421: return $modified;
1.1 matthew 422: }
423:
424: #################################################################
425: #################################################################
426:
427: =pod
428:
1.9 raeburn 429: =over 4
430:
431: =item &parse_config_file()
1.1 matthew 432:
433: Read a configuration file in and parse it into an internal data structure.
434:
435: Input: filename
436:
437: Output: array ref $filedata OR scalar error message
438:
1.9 raeburn 439: =back
440:
1.1 matthew 441: =cut
442:
443: #################################################################
444: #################################################################
445: sub parse_config_file {
446: my ($file) = @_;
447: open(INFILE,$file) || return ('Unable to open '.$file.' for reading');
448: my @Input = <INFILE>;
449: close(INFILE);
450: my @Structure;
451: my %Sections;
452: while (my $line = shift(@Input)) {
453: chomp($line);
454: if ($line =~ /^\[([^\]]*)\]/) {
455: my $section_id = $1;
456: push(@Structure,'__section__'.$section_id);
457: while ($line = shift(@Input)) {
1.4 matthew 458: chomp($line);
1.1 matthew 459: if ($line =~ /^\[([^\]]*)\]/) {
460: unshift(@Input,$line);
461: last;
462: } else {
463: push(@{$Sections{$section_id}},$line);
464: }
465: }
466: } else {
467: push(@Structure,$line);
468: }
469: }
470: my $filedata = [\@Structure,\%Sections];
471: return $filedata;
472: }
473:
474: #################################################################
475: #################################################################
476:
477: =pod
478:
1.9 raeburn 479: =over 4
480:
1.24 ! raeburn 481: =item &write_config_file()
1.1 matthew 482:
483: Write a configuration file out based on the internal data structure returned
484: by &parse_config_file
485:
486: Inputs: filename, $filedata (the return value of &parse_config_file
487:
488: Returns: undef on success, scalar error message on failure.
489:
1.9 raeburn 490: =back
491:
1.1 matthew 492: =cut
493:
494: #################################################################
495: #################################################################
496: sub write_config_file {
497: my ($file,$filedata) = @_;
498: my ($structure,$sections) = @$filedata;
499: if (! defined($structure) || ! ref($structure)) {
500: return 'Bad subroutine inputs';
501: }
1.18 raeburn 502: open(OUTPUT,'>',$file) || return('Unable to open '.$file.' for writing');
1.1 matthew 503: for (my $i=0;$i<scalar(@$structure);$i++) {
504: my $line = $structure->[$i];
505: chomp($line);
506: if ($line =~ /^__section__(.*)$/) {
507: my $section_id = $1;
508: print OUTPUT ('['.$section_id.']'.$/);
509: foreach my $section_line (@{$sections->{$section_id}}) {
510: chomp($section_line);
511: print OUTPUT $section_line.$/;
512: }
513: # Deal with blank lines
514: if ($sections->{$section_id}->[-1] =~ /^\s*$/) {
515: # No need to output a blank line at the end if there is one
516: # already
517: } else {
518: print OUTPUT $/;
519: }
520: } else {
521: print OUTPUT $line.$/;
522: }
523: }
524: close OUTPUT;
525: return undef;
526: }
527:
528: #################################################################
529: #################################################################
530:
531: =pod
532:
1.9 raeburn 533: =over 4
534:
535: =item &modify_config_file()
1.1 matthew 536:
537: Modifies the internal data structure of a configuration file to include new
538: sections and/or new configuration directives.
539:
540: Inputs: $filedata (see &parse_config_file
541: $section, the [section] the new entry is to reside in. A value of undef will
542: cause the "outer" section (as in yum.conf) to be updated (or have the new
543: value prepended).
544: $newkey: A line which matches this will be replaced with $newkey.$newvalue
545: $newvalue: The new value to be placed with the new key.
546:
1.4 matthew 547: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
548:
1.9 raeburn 549: =back
1.4 matthew 550:
1.1 matthew 551: =cut
552:
553: #################################################################
554: #################################################################
555: sub modify_config_file {
556: my ($filedata,$section,$newkey,$newvalue)=@_;
1.4 matthew 557: my $modified = 0; # returned value - set to true if the file is modified
1.1 matthew 558: my ($structure,$sections) = @$filedata;
559: if (! defined($newvalue)) {
560: $newvalue = '';
561: }
562: my $newline = $newkey.$newvalue;
563: #
564: # Determine which array ref gets the item
565: my $target;
566: if (defined($section)) {
567: if (! exists($sections->{$section})) {
568: push(@$structure,'__section__'.$section);
569: $sections->{$section}=[];
570: }
571: $target = $sections->{$section};
572: } else {
573: $target = $structure;
574: }
575: #
576: # Put the item in or update it.
577: my $key_is_new = 1;
578: for (my $i=0;$i<scalar(@$target);$i++) {
579: if ($target->[$i] =~/^$newkey/) {
1.4 matthew 580: if ($target->[$i] ne $newline) {
581: $target->[$i]=$newline;
582: $modified = 1;
583: }
1.1 matthew 584: $key_is_new = 0;
585: last;
586: }
587: }
588: if ($key_is_new) {
589: if (! defined($section)) {
590: unshift(@$target,$newline);
591: } else {
592: # No need to put things after a blank line.
1.2 matthew 593: if (defined($target->[-1]) && $target->[-1] =~ /^\s*$/) {
1.1 matthew 594: $target->[-1] = $newline;
1.4 matthew 595: $modified = 1;
1.1 matthew 596: } else {
597: push(@$target,$newline);
1.4 matthew 598: $modified = 1;
1.1 matthew 599: }
600: }
601: }
1.4 matthew 602: return $modified;
1.1 matthew 603: }
604:
1.9 raeburn 605: #################################################################
606: #################################################################
607:
608: =pod
609:
610: =over 4
611:
612: =item &update_rhn_source()
613:
614: Modifies the Red Hat 4 sources file which includes repositories used by up2date
615:
616: Inputs:
617: $rhn_items - a reference to hash of a hash containing the regular expression
618: to test for, and the text string to append to the file, if an entry for the
619: LON-CAPA RHEL repository is missing for two cases:
620:
621: (a) basearch
622: (b) noarch
623:
624: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
625:
626: =back
627:
628: =cut
629:
630: #################################################################
631: #################################################################
632: sub update_rhn_source {
633: my ($rhn_items) = @_;
634: return 0 if (ref($rhn_items) ne 'HASH');
635: return 0 if ((ref($rhn_items->{basearch}) ne 'HASH') || (ref($rhn_items->{noarch}) ne 'HASH'));
636: my $file = '/etc/sysconfig/rhn/sources';
637: return 0 if (! -e $file);
638: my $backup = $file.'.backup';
639: if (! copy($file,$backup)) {
640: warn "**** Error: Unable to make backup of $file";
641: return 0;
642: }
643: my $result = 0;
644: my $fh;
1.18 raeburn 645: if (open($fh,'<',$file)) {
1.9 raeburn 646: my $total = 0;
647: my %found;
648: foreach my $item (keys(%{$rhn_items})) {
649: $found{$item} = 0;
650: }
651: while(<$fh>) {
652: foreach my $item (keys(%{$rhn_items})) {
653: if (ref($rhn_items->{$item}) eq 'HASH') {
654: my $pattern = $rhn_items->{$item}->{regexp};
655: if ($pattern ne '') {
656: if (m{^$pattern}) {
657: $found{$item} = 1;
658: $total ++;
659: }
660: }
661: }
662: }
663: last if $total == 2;
664: }
665: close($fh);
666: if ($total < 2) {
1.18 raeburn 667: if (open($fh,'>>',$file)) {
1.9 raeburn 668: foreach my $item (keys(%{$rhn_items})) {
669: unless ($found{$item}) {
670: if (ref($rhn_items->{$item}) eq 'HASH') {
671: if ($rhn_items->{$item}->{text} ne '') {
672: print $fh "\n".$rhn_items->{$item}->{text}."\n";
673: $result = 1;
674: }
675: }
676: }
677: }
678: close($fh);
679: }
680: }
681: }
682: return $result;
683: }
1.1 matthew 684:
685: #################################################################
686: #################################################################
687:
688: =pod
689:
1.9 raeburn 690: =over 4
691:
692: =item &update_apt_source()
693:
1.24 ! raeburn 694: Modifies either the sources.list or sources.list.d/loncapa.list
! 695: file which include repositories used by apt-get.
1.9 raeburn 696:
697: Inputs:
1.24 ! raeburn 698: $distname - distro (without version): debian or ubuntu
! 699: $distver - distro version, e.g., 12 or 24
! 700: $deb_row - a reference to a hash containing the regular expression
! 701: to test for, and the text string to append to the file, if an entry
! 702: for the LON-CAPA Debian/ or Ubuntu repository is missing.
1.9 raeburn 703:
704: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
705:
1.1 matthew 706: =back
707:
708: =cut
709:
710: #################################################################
711: #################################################################
1.9 raeburn 712: sub update_apt_source {
1.24 ! raeburn 713: my ($distname,$distver,$deb_row) = @_;
1.9 raeburn 714: return 0 if (ref($deb_row) ne 'HASH');
715: return 0 if (($deb_row->{regexp} eq '') || ($deb_row->{text} eq ''));
716: my $file = '/etc/apt/sources.list';
1.24 ! raeburn 717: my $nobackup;
! 718: if ((($distname eq 'ubuntu') && ($distver > 20)) ||
! 719: (($distname eq 'debian') && ($distver >= 10))) {
! 720: $file = '/etc/apt/sources.list.d/loncapa.list';
! 721: $nobackup = 1;
! 722: }
1.9 raeburn 723: return 0 if (! -e $file);
1.24 ! raeburn 724: unless ($nobackup) {
! 725: my $backup = $file.'.backup';
! 726: if (! copy($file,$backup)) {
! 727: warn "**** Error: Unable to make backup of $file";
! 728: return 0;
! 729: }
1.9 raeburn 730: }
731: my $result = 0;
732: my $fh;
1.18 raeburn 733: if (open($fh,'<',$file)) {
1.9 raeburn 734: my $found = 0;
735: my $pattern = $deb_row->{regexp};
736: while(<$fh>) {
737: if (m{^$pattern}) {
738: $found = 1;
739: last;
740: }
741: }
742: close($fh);
743: if (!$found) {
1.18 raeburn 744: if (open($fh,'>>',$file)) {
1.9 raeburn 745: print $fh "\n".$deb_row->{text}."\n";
746: close($fh);
747: $result = 1;
748: }
749: }
750: }
751: return $result;
752: }
753:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>