#!/usr/bin/env perl # # vim: set ts=4:noet # # sboconfig # script to handle sbotools configuration # # authors: Jacob Pipkin # Luke Williams # license: WTFPL use 5.16.0; use strict; use warnings FATAL => 'all'; use SBO::Lib; use File::Basename; use Getopt::Long; use File::Copy; use File::Path qw(make_path); use File::Temp qw(tempfile);; my $self = basename($0); sub show_usage() { print < 'NOCLEAN', distclean => 'DISTCLEAN', jobs => 'JOBS', 'pkg-dir' => 'PKG_DIR', 'sbo-home' => 'SBO_HOME', ); my %params = ( NOCLEAN => 'c|--noclean', DISTCLEAN => 'd|--distclean', JOBS => 'j|--jobs', PKG_DIR => 'p|--pkg-dir', SBO_HOME => 's|--sbo-home', ); if (exists $options{list}) { my @keys = sort {$a cmp $b} keys %config; say "sboconfig -$params{$_}:\n $_=$config{$_}" for @keys; exit 0; } show_usage and exit 0 unless keys %options > 0; # setup what's being changed, sanity check. my %changes; while (my ($key, $value) = each %valid_confs) { $changes{$value} = $options{$key} if exists $options{$key}; } my $die = 'You have provided an invalid parameter for'; if (exists $changes{NOCLEAN}) { die "$die -c\n" unless $changes{NOCLEAN} =~ /^(TRUE|FALSE)$/; } if (exists $changes{DISTCLEAN}) { die "$die -d\n" unless $changes{DISTCLEAN} =~ /^(TRUE|FALSE)$/; } if (exists $changes{JOBS}) { die "$die -j\n" unless $changes{JOBS} =~ /^(\d+|FALSE)$/; } if (exists $changes{PKG_DIR}) { die "$die -p\n" unless $changes{PKG_DIR} =~ qr#^(/|FALSE$)#; } if (exists $changes{SBO_HOME}) { die "$die -s\n" unless $changes{SBO_HOME} =~ qr#^/#; } # safely modify our conf file; write its contents to a temp file, modify the # temp file, write the contents of the temp file back to the conf file # TODO: if multiple options are provided to this script, this sub should write # them all at once, instead of only a single one and having to call it once for # each option specified to the script. sub config_write { exists $_[1] or script_error 'config_write requires two arguments.'; my ($key, $val) = @_; if (! -d $conf_dir) { mkdir $conf_dir or die "Unable to create $conf_dir. Exiting.\n"; } if (-f $conf_file) { my $tempfh = tempfile(DIR => $tempdir); my $conffh = open_read $conf_file; my $conftents = do {local $/; <$conffh>}; print {$tempfh} $conftents; # tie the temp file so that if $key is already there, we just change # that line and untie it tie my @temp, 'Tie::File', $tempfh; my $has; my $regex = qr/\A\Q$key\E=/; FIRST: for my $tmpline (@temp) { $has++, $tmpline = "$key=$val", last FIRST if $tmpline =~ $regex; } untie @temp; # otherwise, append our new $key=$value pair print {$tempfh} "$key=$val\n" unless $has; # then overwrite the conf file with the contents of the temp file seek $tempfh, 0, 0; my $contents = do {local $/; <$tempfh>}; close $conffh; eval { $conffh = open_fh($conf_file, '>') }; warn "Cannot write configuration: $@\n" and return if $@; print {$conffh} $contents or return; close $conffh, close $tempfh; } else { # no config file, easiest case of all. my $fh = open_fh($conf_file, '>') or return; print {$fh} "$key=$val\n"; close $fh; } return 1; } while (my ($key, $value) = each %changes) { say "Setting $key to $value..."; config_write($key, $value) or warn "Unable to write to $conf_file\n"; } exit 0;