From b7206fc83a227ad39e49ebf8ce968f9feae603d8 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Tue, 21 Apr 2026 12:00:30 +0200 Subject: [PATCH] make config handling more user friendly --- readconfig.pl | 205 ++++++++++++++++++++++++++++++++++++----------- smart.conf.cmake | 5 ++ 2 files changed, 165 insertions(+), 45 deletions(-) diff --git a/readconfig.pl b/readconfig.pl index 406b6de..eac3824 100644 --- a/readconfig.pl +++ b/readconfig.pl @@ -1,11 +1,10 @@ -# # SMArT -# +# # Configuration file code -# +# # Copyright 2001 Wilmer van der Gaast (lintux@lintux.cx) -# -# +# +# # 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 @@ -22,7 +21,7 @@ # # -my( @info, @conf, $l ); +my( @info, @conf, @rawconf, $l ); $info[1] = 'Volume'; $info[2] = 'Server name'; @@ -79,19 +78,25 @@ $info[400] = 'nwserv.stations file'; $info[401] = 'Reply to nearest server requests'; $info[402] = 'Reply to connect requests'; -open( CONF, '<' . $mars_config ); +open( CONF, '<' . $mars_config ) or die "Could not open $mars_config: $!"; @conf = (); +@rawconf = (); + while( $l = ) { - $l =~ s/[\r\n]//g; - $l =~ s/[\t ]+/ /g; - $l =~ s/#.*//; - $l =~ s/^[\t ]*//; - $l =~ s/[\t ]*$//; - if( $l ne '' ) - { - unshift( @conf, $l ); - } + push( @rawconf, $l ); + + my $x = $l; + $x =~ s/[\r\n]//g; + $x =~ s/[\t ]+/ /g; + $x =~ s/#.*//; + $x =~ s/^[\t ]*//; + $x =~ s/[\t ]*$//; + + if( $x ne '' ) + { + push( @conf, $x ); + } } close( CONF ); @@ -99,53 +104,163 @@ sortconfig(); sub sortconfig() { - @conf = sort( { $a cmp $b } @conf ); - @conf = sort( { ( split( ' ', $a ) )[0] <=> ( split( ' ', $b ) )[0] } @conf ); + @conf = sort( { $a cmp $b } @conf ); + @conf = sort( { ( split( ' ', $a ) )[0] <=> ( split( ' ', $b ) )[0] } @conf ); } sub getconfigline( $ ) { - my( @c, $c ); - - @c = getconfig( @_ ); - $c = $c[0]; - $c =~ s/^[0-9]* //; - return( $c ); + my( @c, $c ); + + @c = getconfig( @_ ); + $c = $c[0]; + $c =~ s/^[0-9]* //; + return( $c ); } sub getconfig( $ ) { - my( @c ); - - @c = grep( /^$_[0] /i, @conf ); - return( @c ); + my( @c ); + + @c = grep( /^$_[0] /i, @conf ); + return( @c ); } sub addconfigline( $ ) { - unshift( @conf, $_[0] ); + unshift( @conf, $_[0] ); } sub delconfigline( $ ) { - @conf = grep( !/^$_[0] /i, grep( !/^$_[0]$/i, @conf ) ); + @conf = grep( !/^$_[0] /i, grep( !/^$_[0]$/i, @conf ) ); +} + +sub normalize_line( $ ) +{ + my $x = $_[0]; + + $x =~ s/[\r\n]//g; + $x =~ s/[\t ]+/ /g; + $x =~ s/#.*//; + $x =~ s/^[\t ]*//; + $x =~ s/[\t ]*$//; + + return( $x ); +} + +sub section_of_line( $ ) +{ + my $x = normalize_line( $_[0] ); + + if( $x =~ /^([0-9]+)\b/ ) + { + return( $1 ); + } + + return( '' ); +} + +sub writeconfig_compact() +{ + my( $i, $l ); + + sortconfig(); + + open( CONF, '>' . $mars_config ) or die "Could not write $mars_config: $!"; + + $l = ( getconfig( '1 SYS' ) )[0]; + delconfigline( '1 SYS' ); + addconfigline( $l ); + + foreach $i ( @conf ) + { + $l = $i; + $l =~ s/ .*//; + printf( CONF "%-50s # %s\n", $i, $info[$l] ); + } + + close( CONF ); +} + +sub writeconfig_preserve_layout() +{ + my( %secmap, %written, @sections, $sec, $line, $sysline ); + + sortconfig(); + + # Keep SYS as the first entry in section 1. + $sysline = ( grep( /^1 SYS /, @conf ) )[0]; + if( defined( $sysline ) ) + { + @conf = grep( $_ ne $sysline, @conf ); + unshift( @conf, $sysline ); + } + + foreach $line ( @conf ) + { + $sec = section_of_line( $line ); + if( $sec ne '' ) + { + push( @{ $secmap{$sec} }, $line ); + } + } + + open( CONF, '>' . $mars_config ) or die "Could not write $mars_config: $!"; + + foreach $line ( @rawconf ) + { + $sec = section_of_line( $line ); + + # Preserve comments and blank lines exactly as they were. + if( $sec eq '' ) + { + print CONF $line; + next; + } + + # Replace each section only once, at its first occurrence. + if( ! $written{$sec} ) + { + if( defined( $secmap{$sec} ) ) + { + foreach my $entry ( @{ $secmap{$sec} } ) + { + print CONF $entry . "\n"; + } + } + $written{$sec} = 1; + } + + # Skip the original config line because the updated section + # has already been emitted. + } + + # Append sections that did not exist in the original file. + @sections = sort { $a <=> $b } keys( %secmap ); + foreach $sec ( @sections ) + { + next if $written{$sec}; + + print CONF "\n"; + foreach my $entry ( @{ $secmap{$sec} } ) + { + print CONF $entry . "\n"; + } + $written{$sec} = 1; + } + + close( CONF ); } sub writeconfig() { - my( $i, $l ); - - sortconfig(); - - open( CONF, '>' . $mars_config ); - $l = ( getconfig( '1 SYS' ) )[0]; - delconfigline( '1 SYS' ); - addconfigline( $l ); - foreach $i ( @conf ) - { - $l = $i; - $l =~ s/ .*//; - printf( CONF "%-50s # %s\n", $i, $info[$l] ); - } - close( CONF ); + if( defined( $smart_compact_nwservconf ) && $smart_compact_nwservconf ) + { + writeconfig_compact(); + } + else + { + writeconfig_preserve_layout(); + } } diff --git a/smart.conf.cmake b/smart.conf.cmake index 11a999f..f1923d5 100644 --- a/smart.conf.cmake +++ b/smart.conf.cmake @@ -37,6 +37,11 @@ $mars_config = '@MARS_NWE_INSTALL_FULL_CONFDIR@/nwserv.conf'; # Keep this set to an unprivileged local account. $nonroot_user = 'nobody'; +# Write the mars_nwe configuration file in compact form. +# 0 = preserve comments, blank lines and the original section layout +# 1 = write a compact configuration file without the original long comments +$smart_compact_nwservconf = 0; + # ------------------------------------------------------------ # SMArT internal file layout # ------------------------------------------------------------