#!/usr/bin/perl

eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell

#   $Id: scconf_tool 5148 2006-07-14 16:19:36Z efocht $

#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.

#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#
#   Tool for editing systemconfigurator.conf files from the shell.
#
#   Written by Erich Focht, July 2006
#


use strict;
use vars qw($VERSION);
$VERSION = sprintf("%d", q$Revision: 5148 $ =~ /(\d+)/);
use POSIX;
use Carp;
use Getopt::Long;

my ($block, $var, $val, $read, $set, $verbose, $scconf, $outfile, $quiet);
GetOptions(
           "block=s"   => \$block,
           "var=s"     => \$var,
           "val=s"     => \$val,
	   "set|s"     => \$set,
	   "out|o=s"   => \$outfile,
           "verbose"   => \$verbose,
           "quiet|q"   => \$quiet,
           ) || &usage();

&usage if (scalar(@ARGV) != 1);
$scconf = $ARGV[0];

$read = 1 if (!$set);

if (!$block || !$var) {
    print "You MUST specify a block and a variable!\n";
    &usage;
}

open IN, "$scconf" or
    die "Could not open file $scconf";
my @out;
my ($inblock, $invar, $icont, $blank) = ( 0, 0, 0, "");
my ($thisvar, $thisblock, $thisval, @value, $set_done);
while (<IN>) {
    chomp;
    
    if ($icont && $inblock && $invar) {
	if (/\\\s*$/) {
	    s/\\\s*$//;
	    $icont = 1;
	} else {
	    $icont = 0;
	}
	push @value, $_;
	next;
    }
    if (/^\s*\[(.*)\]/) {
	$thisblock = $1;
	if (!$inblock) {
	    if ($thisblock eq $block) {
		$inblock = 1;
	    }
	} else {
	    # we were in the appropriate block, it just ended
	    if ($invar || ($set && !$set_done)) {
		&do_var();
	    }
	    $inblock = 0;
	    $invar = 0;
	}
    } elsif (/^(\s*)(\w+)\s*=\s*(.*)$/) {
	$blank   = $1;
	$thisvar = $2;
	$thisval = $3;
	if ($inblock) {
	    if (!$invar) {
		if ($thisvar eq $var) {
		    # make sure we read the complete variable
		    $invar = 1;

		    if ($thisval =~ /\\\s*$/) {
			$thisval =~ s/\\\s*$//;
			push @value, $thisval;
			$icont = 1;
		    } else {
			push @value, $thisval;
		    }
		    next;
		}
	    } else {
		# just read another variable after finishing the one we
		# were looking for
		&do_var();
		$invar = 0;
	    }
	}
    } 
    if ($set) {
	push @out, $_;
    }
}
close IN;
# finish up
if ($inblock && ($invar || ($set && !$set_done))) {
    &do_var();
}

if ($outfile) {
    open OUT, "> $outfile" or
	die "Could not open file $outfile";
    map { print OUT "$_\n"; } @out;
    close OUT;
} else {
    map { print "$_\n"; } @out;
}
exit 0;


sub do_var {
    if (!$set) {
	$val = join(" ",@value);
    } else {
	$set_done = 1;
    }
    if (($val =~ /\s/) && !($val =~ m/^\".*\"$/)) {
	$val = "\"$val\"";
    }
    if ($quiet) {
	push @out, "$val";
    } else {
	push @out, "$blank$var = $val";
    }
}

sub usage {
    my $progname = $0;
    if ($progname =~ m/(.+\/)(\w+)/) {
	$progname = $2;
    }
    print <<USAGE;
Read information from a systemconfig.conf file or set variable values.

Usage: $progname [ operation ] <options> scconf_file
  operation
    -s, --set               set variable value (default: read)

  options
    --block <BLOCK>   specify configuration block name
    --var <VARIABLE>  specify variable to be read or changed
    --val <VALUE>     specify variable value (for --set, only)
    --out <FILE>      output filename. If not set, use STDOUT.


USAGE
    exit;
}

__END__
