You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeadmin/knetworkconf/backends/general.pl.in

645 lines
18 KiB

#!/usr/bin/env perl
#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# Common stuff for the ximian-setup-tools backends.
#
# Copyright (C) 2000-2001 Ximian, Inc.
#
# Authors: Hans Petter Jansson <hpj@ximian.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library 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 Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
$SCRIPTSDIR = "@scriptsdir@";
if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
{
$SCRIPTSDIR = ".";
$DOTIN = ".in";
}
require "$SCRIPTSDIR/report.pl$DOTIN";
require "$SCRIPTSDIR/platform.pl$DOTIN";
require "$SCRIPTSDIR/xml.pl$DOTIN";
eval "use Locale::gettext";
$eval_gettext = $@;
eval "use POSIX";
$eval_posix = $@;
eval "use Encode";
$eval_encode = $@;
$has_i18n = (($eval_gettext eq "") && ($eval_posix eq "") && ($eval_encode eq ""));
if ($has_i18n)
{
# set up i18n stuff
&setlocale (LC_MESSAGES, "");
&bindtextdomain ("@GETTEXT_PACKAGE@", "@localedir@");
# Big stupid hack, but it's the best I can do until
# distros switch to perl's gettext 1.04...
eval "&bind_textdomain_codeset (\"@GETTEXT_PACKAGE@\", \"UTF-8\")";
&textdomain ("@GETTEXT_PACKAGE@");
eval "sub _ { return gettext (shift); }";
}
else
{
# fake the gettext calls
eval "sub _ { return shift; }";
}
# --- Operation modifying variables --- #
# Variables are set to their default value, which may be overridden by user. Note
# that a $prefix of "" will cause the configurator to use '/' as the base path,
# and disables creation of directories and writing of previously non-existent
# files.
# We should get rid of all these globals.
$gst_name = ""; # Short name of tool.
# $gst_version = ""; # Version of tool - [major.minor.revision]. Deprecated: now in hash
# structure generated by &gst_init.
# $gst_operation = ""; # Major operation user wants to perform - [get | set | filter]. Same as gst_version.
$gst_prefix = "";
$gst_do_verbose = 0;
$gst_do_report = 0;
$gst_debug = 0;
$gst_do_immediate = 1;
# Location management stuff
$gst_location = "";
$gst_no_archive = 0;
sub gst_print_usage_synopsis
{
my ($tool) = @_;
my ($ops_syn, $i);
my @ops = qw (get set filter);
foreach $i (@ops)
{
$ops_syn .= "--$i | " if exists $ {$$tool{"directives"}}{$i};
}
print STDERR "Usage: $$tool{name}-conf <${ops_syn}--interface | --directive | --help | --version>\n";
print STDERR " " x length $$tool{"name"};
print STDERR " [--disable-immediate] [--prefix <location>]\n";
print STDERR " " x length $$tool{"name"};
print STDERR " [--progress] [--report] [--verbose]\n\n";
}
sub gst_print_usage_generic
{
my ($tool) = @_;
my (%usage, $i);
my @ops = qw (get set filter);
my $usage_generic_head =<< "end_of_usage_generic;";
Major operations (specify one of these):
end_of_usage_generic;
my $usage_generic_tail =<< "end_of_usage_generic;";
-i --interface Shows the available backend directives for interactive mode,
in XML format.
Interactive mode is set when no -g, -s or -f arguments are
given.
-d --directive <directive> Takes a \'name::arg1::arg2...::argN\' directive
value as comming from standard input in interactive mode.
-h --help Prints this page to standard error.
--version Prints version information to standard output.
Modifiers (specify any combination of these):
--platform <name-ver> Overrides the detection of your platform\'s
name and version, e.g. redhat-6.2. Use with care. See the
documentation for a full list of supported platforms.
--disable-immediate With --set, prevents the configurator from
running any commands that make immediate changes to
the system configuration. Use with --prefix to make a
dry run that won\'t affect your configuration.
With --get, suppresses running of non-vital external
programs that might take a long time to finish.
-p --prefix <location> Specifies a directory prefix where the
configuration is looked for or stored. When storing
(with --set), directories and files may be created.
--progress Prints machine-readable progress information to standard
output, before any XML, consisting of three-digit
percentages always starting with \'0\'.
--report Prints machine-readable diagnostic messages to standard
output, before any XML. Each message has a unique
three-digit ID. The report ends in a blank line.
-v --verbose Prints human-readable diagnostic messages to standard
error.
end_of_usage_generic;
$usage{"get"} =<< "end_of_usage_generic;";
-g --get Prints the current configuration to standard output, as
a standalone XML document. The configuration is read from
the host\'s system config files.
end_of_usage_generic;
$usage{"set"} =<< "end_of_usage_generic;";
-s --set Updates the current configuration from a standalone XML
document read from standard input. The format is the same
as for the document generated with --get.
end_of_usage_generic;
$usage{"filter"} =<< "end_of_usage_generic;";
-f --filter Reads XML configuration from standard input, parses it,
and writes the configurator\'s impression of it back to
standard output. Good for debugging and parsing tests.
end_of_usage_generic;
print STDERR $usage_generic_head;
foreach $i (@ops)
{
print STDERR $usage{$i} if exists $ {$$tool{"directives"}}{$i};
}
print STDERR $usage_generic_tail;
}
# if $exit_code is provided (ne undef), exit with that code at the end.
sub gst_print_usage
{
my ($tool, $exit_code) = @_;
&gst_print_usage_synopsis ($tool);
print STDERR $$tool{"description"} . "\n";
&gst_print_usage_generic ($tool);
exit $exit_code if $exit_code ne undef;
}
sub gst_print_version
{
my ($tool, $exit_code) = @_;
print "$$tool{name} $$tool{version}\n";
exit $exit_code if $exit_code ne undef;
}
# --- Initialization and finalization --- #
sub gst_set_operation
{
my ($tool, $operation) = @_;
if ($tool{"operation"} ne "")
{
print STDERR "Error: You may specify only one major operation.\n\n";
&gst_print_usage ($tool, 1);
exit (1);
}
$$tool{"operation"} = $operation;
}
sub gst_set_with_param
{
my ($tool, $arg_name, $value) = @_;
if ($$tool{$arg_name} ne "")
{
print STDERR "Error: You may specify --$arg_name only once.\n\n";
&gst_print_usage ($tool, 1);
}
if ($value eq "")
{
print STDERR "Error: You must specify an argument to the --$arg_name option.\n\n";
&gst_print_usage ($tool, 1);
}
$$tool{$arg_name} = $value;
}
sub gst_set_op_directive
{
my ($tool, $directive) = @_;
&gst_set_with_param ($tool, "directive", $directive);
&gst_set_operation ($tool, "directive");
}
sub gst_set_prefix
{
my ($tool, $prefix) = @_;
&gst_set_with_param ($tool, "prefix", $prefix);
$gst_prefix = $prefix;
}
sub gst_set_dist
{
my ($tool, $dist) = @_;
&gst_set_with_param ($tool, "platform", $dist);
$gst_dist = $dist;
}
sub gst_set_location
{
my ($tool, $location) = @_;
&gst_set_with_param ($tool, "location", $location);
$gst_location = $location;
}
sub gst_merge_std_directives
{
my ($tool) = @_;
my ($directives, $i);
my %std_directives =
(
# platforms directive to do later.
"platforms" => [ \&gst_platform_list, [],
"Print XML showing platforms supported by backend." ],
"platform_set" => [ \&gst_platform_set, ["platform"],
"Force the selected platform. platform arg must be one of the listed in the" .
"reports." ],
"interface" => [ \&gst_interface_directive, [],
"Print XML showing backend capabilities." ],
"end" => [ \&gst_end_directive, [],
"Finish gracefuly and exit with success." ]
);
$directives = $$tool{"directives"};
# Standard directives may be overriden.
foreach $i (keys %std_directives)
{
$$directives{$i} = $std_directives{$i} if !exists $$directives{$i};
}
}
sub gst_is_tool
{
my ($tool) = @_;
if ((ref $tool eq "HASH") &&
(exists $$tool{"is_tool"}) &&
($$tool{"is_tool"} == 1))
{
return 1;
}
return 0;
}
sub gst_init
{
my ($name, $version, $description, $directives, @args) = @_;
my (%tool, $arg);
# print a CR for synchronysm with the frontend
print "\n";
# Set the output autoflush.
$old_fh = select (STDOUT); $| = 1; select ($old_fh);
$old_fh = select (STDERR); $| = 1; select ($old_fh);
$tool{"is_tool"} = 1;
# Set backend descriptors.
$tool{"name"} = $gst_name = $name;
$tool{"version"} = $version;
$tool{"description"} = $description;
$tool{"directives"} = $directives;
&gst_merge_std_directives (\%tool);
# Parse arguments.
while ($arg = shift (@args))
{
if ($arg eq "--get" || $arg eq "-g") { &gst_set_operation (\%tool, "get"); }
elsif ($arg eq "--set" || $arg eq "-s") { &gst_set_operation (\%tool, "set"); }
elsif ($arg eq "--filter" || $arg eq "-f") { &gst_set_operation (\%tool, "filter"); }
elsif ($arg eq "--directive" || $arg eq "-d") { &gst_set_op_directive (\%tool, shift @args); }
elsif ($arg eq "--interface" || $arg eq "-i") { &gst_interface_print (\%tool, 0); }
elsif ($arg eq "--help" || $arg eq "-h") { &gst_print_usage (\%tool, 0); }
elsif ($arg eq "--version") { &gst_print_version (\%tool, 0); }
elsif ($arg eq "--prefix" || $arg eq "-p") { &gst_set_prefix (\%tool, shift @args); }
elsif ($arg eq "--platform") { &gst_set_dist (\%tool, shift @args); }
elsif ($arg eq "--progress") { $tool{"progress"} = $gst_progress = 1; }
elsif ($arg eq "--location") { &gst_set_location (\%tool, shift @args); }
elsif ($arg eq "--no-archive") { $tool{"no_archive"} = $gst_no_archive = 1; }
elsif ($arg eq "--debug") { $tool{"debug"} = $gst_debug = 1; }
elsif ($arg eq "--verbose" || $arg eq "-v")
{
$tool{"do_verbose"} = $gst_do_verbose = 1;
&gst_report_set_threshold (99);
}
elsif ($arg eq "--report")
{
$tool{"do_report"} = $gst_do_report = 1;
&gst_report_set_threshold (99);
}
else
{
print STDERR "Error: Unrecognized option '$arg'.\n\n";
&gst_print_usage (\%tool, 1);
}
}
# See if debug requested in env.
$tool{"debug"} = $gst_debug = 1 if ($ENV{"SET_ME_UP_HARDER"});
# Set up subsystems.
&gst_platform_get_system (\%tool);
&gst_platform_guess (\%tool) if !$tool{"platform"};
&gst_report_begin ();
return \%tool;
}
sub gst_terminate
{
&gst_report_set_threshold (-1);
&gst_debug_close_all ();
exit (0);
}
sub gst_end_directive
{
my ($tool) = @_;
&gst_report_end ();
&gst_xml_print_request_end ();
&gst_terminate ();
}
sub gst_interface_print_comment
{
my ($name, $directive) = @_;
my %std_comments =
("get" =>
"Prints the current configuration to standard output, as " .
"a standalone XML document. The configuration is read from " .
"the host\'s system config files.",
"set" =>
"Updates the current configuration from a standalone XML " .
"document read from standard input. The format is the same " .
"as for the document generated with --get.",
"filter" =>
"Reads XML configuration from standard input, parses it, " .
"and writes the configurator\'s impression of it back to " .
"standard output. Good for debugging and parsing tests."
);
$comment = $$directive[2];
$comment = $std_comments{$name} if (exists $std_comments{$name});
if ($comment)
{
&gst_xml_print_line ("<comment>");
&gst_xml_print_line ($comment);
&gst_xml_print_line ("</comment>");
}
}
# if $exit_code is provided (ne undef), exit with that code at the end.
sub gst_interface_print
{
my ($tool, $exit_code) = @_;
my ($directives, $key);
$directives = $$tool{"directives"};
&gst_xml_print_begin ("interface");
foreach $key (sort keys %$directives)
{
my $comment = $ {$$directives{$key}}[2];
my @args = @{ $ {$$directives{$key}}[1]};
my $arg;
&gst_xml_container_enter ("directive");
&gst_xml_print_line ("<name>$key</name>");
&gst_interface_print_comment ($key, $$directives{$key});
while ($arg = shift (@args))
{
if ($arg =~ /\*$/)
{
my $tmp = $arg;
&gst_report ("directive_invalid", $key) if ($#args != -1);
chop $tmp;
&gst_xml_print_line ("<var-arguments>$tmp</var-arguments>");
}
else
{
&gst_xml_print_line ("<argument>$arg</argument>");
}
}
&gst_xml_container_leave ();
}
&gst_xml_print_end ("interface");
exit $exit_code if $exit_code ne undef;
}
sub gst_interface_directive
{
my ($tool) = @_;
&gst_report_end ();
&gst_interface_print ($tool);
}
sub gst_directive_fail
{
my (@report_args) = @_;
&gst_report (@report_args);
&gst_report_end ();
&gst_xml_print_request_end ();
&gst_debug_close_all ();
}
# This sepparates a line in args by the directive line format,
# doing the necessary escape sequence manipulations.
sub gst_directive_parse_line
{
my ($line) = @_;
my ($arg, @args);
chomp $line;
$line =~ s/\\\\/___escape\\___/g;
$line =~ s/\\::/___escape2:___/g;
@args = split ("::", $line);
foreach $arg (@args)
{
$arg =~ s/___escape2:___/::/g;
$arg =~ s/___escape\\___/\\/g;
}
return @args;
}
# Normal use for the direcives hash in the backends is:
#
# "name" => [ \&sub, [ "arg1", "arg2", "arg3",... "argN" ], "comment" ]
#
# name name of the directive that will be used in interactive mode.
# sub is the function that runs the directive.
# arg1...argN show the number of arguments that the function may use. The
# name of the argument is used for documentation purposes for
# the interfaces XML (dumped by the "interfaces" directive).
# An argument ending with * means that 0 or more arguments
# may be given.
# comment documents the directive in a brief way, for the interface XML.
#
# Example:
#
# "install_font" => [ \&gst_font_install, [ "directory", "file", "morefiles*" ], "Installs fonts." ]
#
# This means that when an interactive mode directive is given, such as:
#
# install_font::/usr/share/fonts::/tmp/myfile::/tmp/myfile2
#
# the function gst_font_install will be called, with the tool structure, /usr/share/fonts,
# /tmp/myfile and /tmp/myfile2 as arguments. Directives with 1 or 0 arguments
# would be rejected, as we are requiring 2, and optionaly allowing more.
# Check enable_iface in network-conf.in for an example of a directive handler.
#
# The generated interface XML piece for this entry would be:
#
# <directive>
# <name>gst_font_install</name>
# <comment>
# Installs fonts.
# </comment>
# <argument>directory</argument>
# <argument>file</argument>
# <var-arguments>morefiles</var-arguments>
# </directive>
sub gst_directive_run
{
my ($tool, $line) = @_;
my ($key, @args, $directives, $proc, $reqargs, $i);
($key, @args) = &gst_directive_parse_line ($line);
$directives = $$tool{"directives"};
&gst_report_begin ();
if (!exists $$directives{$key})
{
&gst_directive_fail ("directive_unsup", $key);
return;
}
$reqargs = [];
foreach $i (@{$ {$$directives{$key}}[1]})
{
push @$reqargs, $i if not ($i =~ /\*$/);
}
if (scalar @args < scalar @$reqargs)
{
&gst_directive_fail ("directive_lowargs", $key, scalar (@$reqargs), join (',', $key, @args));
return;
}
$reqargs = $ {$$directives{$key}}[1];
if ((scalar @args != scalar @$reqargs) &&
!($$reqargs[$#$reqargs] =~ /\*$/))
{
&gst_directive_fail ("directive_badargs", $key, scalar (@$reqargs), join (',', $key, @args));
return;
}
&gst_report ("directive_run", $key, join (',', @args));
$proc = $ {$$directives{$key}}[0];
&$proc ($tool, @args);
&gst_xml_print_request_end ();
&gst_debug_close_all ();
}
sub gst_run
{
my ($tool) = @_;
my ($line);
if ($$tool{"operation"} ne "directive")
{
my @stdops = qw (get set filter);
my ($op);
foreach $op (@stdops)
{
if ($$tool{"operation"} eq $op)
{
$$tool{"operation"} = "directive";
$$tool{"directive"} = $op;
}
}
}
&gst_report_end ();
if ($$tool{"directive"})
{
&gst_directive_run ($tool, $$tool{"directive"});
&gst_terminate ();
}
while ($line = <STDIN>)
{
&gst_directive_run ($tool, $line);
}
}
1;