ACC SHELL
#!/usr/bin/perl -w
#
# Author: Martin Vidner <mvidner@suse.cz>
# based on ag_yp_makefile by Dan Vesely (dan@suse.cz)
#
# $Id: ag_mailtable 13710 2004-01-30 16:09:34Z mvidner $
#
# Agent for accessing sendmail and postfix maps described in
# makemap(8) and postmap(1)
#
use strict;
package ag_mailtable;
use ycp;
use YaST::SCRAgent;
use Errno qw(ENOENT);
our @ISA = ("YaST::SCRAgent");
# Global variables:
# The file specifies a map, but we represent it as a list to preserve
# preceding comments and the order of entries.
# list entries:
# { "comment" => " foo\n bar\n", "key" => "root", "value" => "joe, \\root" }
# that is, comments have the leading '#' stripped but not the newline.
# Before the first entry, there can be a leading comment, separated by
# a blank line.
our $leading_comment;
our @table;
our $trailing_comment;
# Parser features:
my $filename;
my $linenum;
my $line_comment;
my $line = "";
my $backslashed_line;
my $separator;
my $oseparator;
my $continue_escaped_newline;
my $continue_leading_blanks;
my $debug = defined($ARGV[0]) && $ARGV[0] eq "-d";
#
# routine to log and return error
#
sub log_error ( $ ) {
my ($err_msg) = @_;
y2error ($err_msg);
return 0;
}
sub dumpit () {
print STDERR "line: '$line' line_comment: '$line_comment'\n";
}
# create a map entry after it has been composed of split lines
sub parse_line ($)
{
my $line = shift;
# is this the first line?
if ($line ne "")
{
if ($line =~ /^(.*?)$separator(.*)$/s)
{
push (@table, { "comment" => $line_comment,
"key" => $1,
"value" => $2 });
}
else
{
log_error ("No separator, $filename:$linenum '$line'");
}
}
}
#
sub parse_file ()
{
$linenum = 0;
$line = "";
$line_comment = "";
$backslashed_line = "";
my $leading_comment_allowed = 1;
$leading_comment = "";
@table = ();
$trailing_comment = "";
if (!open (FILE, $filename))
{
y2error ("$filename: $!") unless ($! == ENOENT);
# a missing file will be fixed by the module anyway
# and y2cc starts all agents :(
return;
}
while (<FILE>)
{
chomp; # \n
++$linenum;
dumpit () if ($debug);
# Escaped newlines: merge them before any other processing.
# Is this one escaped?
if ($continue_escaped_newline && /\\$/)
{
print STDERR "$linenum:continued\n" if ($debug);
chop; # \\
$backslashed_line .= "$_ ";
next;
}
# Was there one already?
if ($backslashed_line ne "")
{
$_ = $backslashed_line . $_;
$backslashed_line = "";
}
# Accept comments
if (/^\#(.*)/)
{
print STDERR "$linenum:comment\n" if ($debug);
$trailing_comment .= "$1\n";
}
elsif (/^$/)
{
if ($leading_comment_allowed)
{
$leading_comment .= $trailing_comment;
$trailing_comment = "";
}
}
else
{
$leading_comment_allowed = 0;
# $line is the previous line, $_ is the current one
if (/^\s+(.*)/)
{
if ($continue_leading_blanks)
{
print STDERR "$linenum:leading blanks\n" if ($debug);
$line .= $_;
$line_comment .= $trailing_comment;
$trailing_comment = "";
}
else
{
log_error ("Leading whitespace, $filename:$linenum");
}
}
else
{
print STDERR "$linenum:regular\n" if ($debug);
# a regular line. process the _previous_ one
# because this one might continue
parse_line ($line);
# next buffer
$line = $_;
$line_comment = $trailing_comment;
$trailing_comment = "";
}
}
}
# end of file, but we must not forget to process the buffer!
parse_line ($line);
# only a comment: make it a leading one
if ($leading_comment_allowed)
{
$leading_comment .= $trailing_comment;
$trailing_comment = "";
}
close (FILE);
}
# take a multiline string and write it to FILE with a hash before each line
sub write_comment ($)
{
my $comment = shift;
foreach my $line (split /\n/, $comment)
{
print FILE "\#$line\n";
}
}
#
sub write_file ()
{
return 1 if (! $YaST::SCRAgent::modified);
open (FILE, ">$filename.YaST2.new") or return log_error ("Creating file: $!");
if ($leading_comment)
{
write_comment ($leading_comment);
print FILE "\n";
}
foreach my $entry (@table)
{
write_comment ($entry->{"comment"});
print FILE $entry->{"key"}, $oseparator, $entry->{"value"}, "\n";
}
write_comment ($trailing_comment);
close (FILE);
if (-f $filename)
{
rename $filename, "$filename.YaST2.save" or return log_error ("Creating backup: $!");
}
rename "$filename.YaST2.new", $filename or return log_error ("Moving temp file: $!");
$YaST::SCRAgent::modified = 0;
return 1;
}
sub check_initialized ()
{
if (!$filename)
{
y2error ("Agent not initialized yet");
}
return !!$filename;
}
sub OtherCommand ()
{
my $class = shift;
my ($symbol, $config, @rest) = @_;
if ($symbol ne "Mailtable")
{
y2error ("The first command must be the configuration.(Seen '$_')");
}
else
{
$filename = $config->{"filename"};
$continue_escaped_newline = $config->{"continue_escaped_newline"};
$continue_leading_blanks = $config->{"continue_leading_blanks"};
$separator = $config->{"colon"} ? qr/:\s+/ : qr/\s+/;
$oseparator = $config->{"colon"} ? ":\t" : "\t";
}
parse_file ();
$YaST::SCRAgent::modified = 0;
print STDERR scalar(@table), " items\n" if ($debug);
return undef;
}
sub Dir_ ()
{
return (["leading_comment", "meta", "table", "trailing_comment"]);
}
sub Dir_meta ()
{
return (["filename"]);
}
# "our" variables are written to implicitly
# this is a special case
sub Write_ ()
{
my $class = shift;
my $argument = shift;
my $result;
if (!defined ($argument))
{
$result = write_file ();
}
else
{
y2error ("Wrong path argument for .: ", ref ($argument));
$result = 0;
}
return $result;
}
# "our" variables are read implicitly
# this is a special case
sub Read_meta_filename ()
{
return $filename;
}
package main;
ag_mailtable->Run ();
ag_mailtable::write_file ();
ACC SHELL 2018