summaryrefslogtreecommitdiffstats
path: root/knetworkconf/backends
diff options
context:
space:
mode:
Diffstat (limited to 'knetworkconf/backends')
-rw-r--r--knetworkconf/backends/AUTHORS5
-rw-r--r--knetworkconf/backends/Makefile.am29
-rw-r--r--knetworkconf/backends/NEWS325
-rw-r--r--knetworkconf/backends/README9
-rw-r--r--knetworkconf/backends/README.NEW_PLATFORMS5
-rw-r--r--knetworkconf/backends/configure.in.in15
-rw-r--r--knetworkconf/backends/debug.pl.in222
-rw-r--r--knetworkconf/backends/file.pl.in934
-rw-r--r--knetworkconf/backends/general.pl.in644
-rwxr-xr-xknetworkconf/backends/guess_system.sh1121
-rwxr-xr-xknetworkconf/backends/mkinstalldirs111
-rwxr-xr-xknetworkconf/backends/network-conf.in639
-rw-r--r--knetworkconf/backends/network.pl.in6605
-rw-r--r--knetworkconf/backends/parse.pl.in1828
-rw-r--r--knetworkconf/backends/platform.pl.in685
-rw-r--r--knetworkconf/backends/process.pl.in54
-rw-r--r--knetworkconf/backends/replace.pl.in1770
-rw-r--r--knetworkconf/backends/report.pl.in366
-rw-r--r--knetworkconf/backends/service-list.pl.in337
-rw-r--r--knetworkconf/backends/service.pl.in2119
-rw-r--r--knetworkconf/backends/system-tools-backends.pc.in14
-rwxr-xr-xknetworkconf/backends/type1inst1387
-rw-r--r--knetworkconf/backends/util.pl.in463
-rw-r--r--knetworkconf/backends/xml.pl.in1012
24 files changed, 20699 insertions, 0 deletions
diff --git a/knetworkconf/backends/AUTHORS b/knetworkconf/backends/AUTHORS
new file mode 100644
index 0000000..b0195bc
--- /dev/null
+++ b/knetworkconf/backends/AUTHORS
@@ -0,0 +1,5 @@
+Arturo Espinosa <arturo@ximian.com>
+Hans Petter Jansson <hpj@ximian.com>
+Tambet Ingo <tambet@ximian.com>
+Carlos Garnacho Parro <carlosg@gnome.org>
+
diff --git a/knetworkconf/backends/Makefile.am b/knetworkconf/backends/Makefile.am
new file mode 100644
index 0000000..7fc54ec
--- /dev/null
+++ b/knetworkconf/backends/Makefile.am
@@ -0,0 +1,29 @@
+backends = \
+ network-conf
+
+perl_libs = \
+ debug.pl \
+ file.pl \
+ general.pl \
+ network.pl \
+ parse.pl \
+ platform.pl \
+ process.pl \
+ replace.pl \
+ report.pl \
+ service.pl \
+ service-list.pl \
+ util.pl \
+ xml.pl
+
+scripts_SCRIPTS = $(backends) $(perl_libs)
+
+EXTRA_DIST = \
+ system-tools-backends.pc.in \
+ AUTHORS
+
+CLEANFILES = $(backends) $(perl_libs) system-tools-backends.pc
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = system-tools-backends.pc
+
diff --git a/knetworkconf/backends/NEWS b/knetworkconf/backends/NEWS
new file mode 100644
index 0000000..3ff2bd4
--- /dev/null
+++ b/knetworkconf/backends/NEWS
@@ -0,0 +1,325 @@
+System Tools Backends Version 1.4.2, 2006-01-02
+-----------------------------------------------
+
+The System Tools Backends version 1.4.1 "Radical cut" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ Network
+ =======
+ - Added support for Ubuntu 5.10 and 6.04, Yoper 2.2, ArkLinux, FC4 and latest Mandrake/Mandriva (Juan Luis Baptiste)
+
+ Services
+ ========
+ - Added support for ArchLinux (Arjan Timmerman)
+
+ Time
+ ====
+ - Added support for ArchLinux (Arjan Timmerman)
+
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.4/
+
+
+System Tools Backends Version 1.4.1, 2005-11-27
+-----------------------------------------------
+
+The System Tools Backends version 1.4.1 "Burning sky" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ Network
+ =======
+ - Fixed network configuration in Gentoo (Christian Meyer, Florian Schricker, garnacho)
+ - Fixed WEP key detection in Slackware (garnacho)
+
+ Common
+ ======
+ - Added support for Slackware 10.2.0 (Scott J. Harmon)
+ - Changed Specifix Linux to rPath Linux (Ken VanDine)
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.4/
+
+
+System Tools Backends Version 1.4.0, 2005-08-23
+-----------------------------------------------
+
+The System Tools Backends version 1.4.0 "Already there" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.4/
+
+
+System Tools Backends Version 1.3.92, 2005-08-23
+-----------------------------------------------
+
+The System Tools Backends version 1.3.92 "Almost there" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ Network
+ =======
+ - enable gateway saving under Slackware and Zenwalk (Jean-Philippe Guillemin)
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.3/
+
+System Tools Backends Version 1.3.2, 2005-08-08
+-----------------------------------------------
+
+The System Tools Backends version 1.3.2 "It's not a rehearsal" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ Services
+ ========
+ - Added more roles for known services (garnacho)
+
+ Users
+ =====
+ - Strings improvements in groups descriptions (Corey Burger, Guillaume Desmottes)
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.3/
+
+System Tools Backends Version 1.3.1, 2005-07-05
+-----------------------------------------------
+
+The System Tools Backends version 1.3.1 "Make me laugh" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ Network
+ =======
+ - do not detect irlan[0-9] interfaces as an[0-9] (garnacho)
+ - other misc fixes (garnacho)
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.3/
+
+System Tools Backends Version 1.3.0, 2005-07-05
+-----------------------------------------------
+
+The System Tools Backends version 1.3.0 "Learning to hate autotools" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ General
+ =======
+ - Added support for Slackware 10.1.0 (Scott J. Harmon)
+ - Added support for VidaLinux 1.2 (Christian Meyer)
+
+ Network
+ =======
+ - wireless handling improvements in Debian (me)
+ - recognize tun ifaces as dialup ones (me)
+ - fixed handling of dhclient v3 (me)
+ - fixed FreeBSD network support (Joe Marcus Clarke)
+ - fixed handling of dhcpcd (Christian Meyer)
+ - Added support for WEP key type (me)
+ - Added support for KUbuntu (Juan Luis Baptiste)
+
+ Time
+ ====
+ - update /etc/timezone in Debian systems
+
+ Services
+ ========
+ - Separate priorities for init types which support them (me)
+ - Add roles to services and runlevels (me)
+
+ Translations
+ ============
+ - el (Nikos Charonitakis)
+ - en_CA (Adam Weinberger)
+ - hu (Szabolcs Varga)
+ - id (Ahmad Riza H Nst)
+ - ne (Jyotsna, Pawan chitrakr)
+ - rw (Steve Murphy)
+ - xh (Adi Attar)
+ - zh_TW (GNOME HK Team)
+
+Downloading
+===========
+You can get it from :
+http://system-tools-backends.freedesktop.org/downloads/1.3/
+
+System Tools Backends Version 1.2.0, 2005-03-07
+-----------------------------------------------
+
+The System Tools Backends version 1.2.0 "Eleee mi niñooo!!" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+Changes since last release
+==========================
+
+ Network
+ =======
+ - Don't activate any interface after having changed if it was disabled (Garnacho)
+
+ Translations
+ ============
+ - hi (Rajesh Ranjan)
+ - hu (Szabolcs Varga)
+ - ja (Takeshi AIHANA)
+ - ro (Mişu Moldovan)
+ - sr, sr@Latn (Danilo Šegan)
+ - vi (Abel Cheung)
+ - zh_TW (GNOME HK Team)
+
+Downloading
+===========
+You can get it from :
+ftp://ftp.gnome.org/pub/GNOME/sources/system-tools-backends/1.2/
+
+System Tools Backends Version 1.1.92, 2005-03-01
+------------------------------------------------
+
+The GNOME System Tools version 1.1.92 "Tararí que te ví" have been released.
+
+The System Tools Backends are a set of cross-platform scripts for Linux and other Unix systems. The backends provide an standard XML interface for modifying the configuration regarless of the distribution that's being used.
+
+Right now the System Tools Backends fully support various distros/OS such as: Redhat, Mandriva, SuSE, Fedora, Debian (and derivations like Ubuntu, Linex, Guadalinex...), Gentoo, Slackware, FreeBSD, OpenNA, PLD, Vine and Specifix.
+
+
+Changes since last release
+==========================
+
+ General
+ =======
+ - Added support for Fedora Core 3 (Garnacho)
+ - i18n fixes (Garnacho)
+
+ Network
+ =======
+ - Added directive for changing default gateway on the fly (Garnacho)
+ - Add support for dhcpcd (Garnacho)
+ - Fixed PPP calling (Michael Vogt, Garnacho)
+
+ Shares
+ ======
+ - Avoid print$ shares (Garnacho)
+
+ Translations
+ ============
+ - bg (Alexander Shopov)
+ - ca (Josep Puigdemont i Casamajó)
+ - el (Kostas Papadimas)
+ - fi (Ilkka Tuohela)
+ - fr (Christophe Merlet)
+ - gu (Ankit Patel)
+ - it (Francesco Marletta)
+ - ko (Young-Ho Cha)
+ - lt (Žygimantas Beručka)
+ - nb (Kjartan Maraas)
+ - nl (Tino Meinen)
+ - pl (GNOME PL Team)
+ - pt (Duarte Loreto)
+ - pt_BR (Raphael Higino)
+ - th (Theppitak Karoonboonyanan)
+ - uk (Maxim Dziumanenko)
+
+Downloading
+===========
+You can get it from :
+ftp://ftp.gnome.org/pub/GNOME/sources/system-tools-backends/1.1/
+
+
+System Tools Backends Version 1.1.91, 2005-02-08
+------------------------------------------------
+
+The GNOME System Tools version 1.1.91 "Ad infinitum" have been released.
+
+The GNOME System Tools are a set of cross-platform configuration utilities for Linux and other Unix systems. The frontends knows nothing about the underlying system and provide the same user interface across the different types of systems. Internally they use the system-tools-backends package.
+
+Changes since last release
+==========================
+
+ General
+ =======
+ - Separate it from the GNOME System Tools frontends (Jeff Waugh, garnacho)
+
+ Network
+ =======
+ - Fixed hosts file parsing when there's more than one line per IP address (garnacho)
+ - Only add an empty PPP interface if it wasn't added before (garnacho)
+ - Use dhclient more reliably (garnacho)
+
+ Time
+ ====
+ - Update the correct server status in Debian (garnacho)
+
+ Users
+ =====
+ - Detect whether to use md5 or not (garnacho)
+ - Made a group description more user friendly (Ole Laursen)
+
+ Translations
+ ============
+ - cs (Miloslav Trmac)
+ - da (Ole Laursen)
+ - de (Frank Arnold)
+ - en_CA (Adam Weinberger)
+ - en_GB (David Lodge)
+ - es (Francisco Javier F. Serrador)
+ - lt (Ŝygimantas Beručka)
+ - pt (Duarte Loreto)
+ - pt_BR (Raphael Higino)
+ - sq (Elian Myftiu)
+ - sv (Christian Rose)
+
+Downloading
+===========
+You can get it from :
+ftp://ftp.gnome.org/pub/GNOME/sources/system-tools-backends/1.1/
diff --git a/knetworkconf/backends/README b/knetworkconf/backends/README
new file mode 100644
index 0000000..0618fe1
--- /dev/null
+++ b/knetworkconf/backends/README
@@ -0,0 +1,9 @@
+to extract the configuracion
+============================
+
+backend --get
+
+to restore the configuration from XML
+=====================================
+
+backend --set < file.xml
diff --git a/knetworkconf/backends/README.NEW_PLATFORMS b/knetworkconf/backends/README.NEW_PLATFORMS
new file mode 100644
index 0000000..dc2d857
--- /dev/null
+++ b/knetworkconf/backends/README.NEW_PLATFORMS
@@ -0,0 +1,5 @@
+If you patch the backends, PLEASE also make a patch with your changes and send it to the author at juan.baptiste@kdemail.net so your changes can be merged with the system-tools-backend project at freedesktop.org .
+
+Thanks.
+Juan Luis Baptiste
+
diff --git a/knetworkconf/backends/configure.in.in b/knetworkconf/backends/configure.in.in
new file mode 100644
index 0000000..44cfc14
--- /dev/null
+++ b/knetworkconf/backends/configure.in.in
@@ -0,0 +1,15 @@
+dnl ==============================================================
+dnl Set SCRIPTS_DIR, FILES_DIR & LOCALE_DIR
+dnl ==============================================================
+KDE_EXPAND_MAKEVAR(KDE_DATADIR, kde_datadir)
+scriptsdir="$KDE_DATADIR/knetworkconf/backends"
+
+AC_SUBST(scriptsdir)
+
+dnl ==============================================================
+dnl END: Set SCRIPTS_DIR, FILES_DIR & LOCALE_DIR
+dnl ==============================================================
+
+dnl Keep the comment on the line below, it works that way.
+dnl AC_OUTPUT(knetworkconf/backends/system-tools-backends.pc knetworkconf/backends/network-conf knetworkconf/backends/debug.pl knetworkconf/backends/file.pl knetworkconf/backends/general.pl knetworkconf/backends/network.pl knetworkconf/backends/parse.pl knetworkconf/backends/platform.pl knetworkconf/backends/process.pl knetworkconf/backends/replace.pl knetworkconf/backends/report.pl knetworkconf/backends/service-list.pl knetworkconf/backends/service.pl knetworkconf/backends/util.pl knetworkconf/backends/xml.pl)
+echo "Backend configured."
diff --git a/knetworkconf/backends/debug.pl.in b/knetworkconf/backends/debug.pl.in
new file mode 100644
index 0000000..1b5b5c1
--- /dev/null
+++ b/knetworkconf/backends/debug.pl.in
@@ -0,0 +1,222 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Functions for hacker debug.
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+use File::Path;
+use File::Copy;
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/general.pl$DOTIN";
+require "$SCRIPTSDIR/file.pl$DOTIN";
+
+
+%gst_debug_fd_hash = ();
+
+
+sub gst_debug_open_output_file
+{
+ local *FILE;
+ my $debug_path = &gst_file_get_debug_path () . "/$gst_name/1/$_[0]";
+
+ if (!exists $gst_debug_fd_hash{$debug_path})
+ {
+ &gst_debug_rotate_try ();
+ open (FILE, ">>$debug_path");
+ $gst_debug_fd_hash{$debug_path} = *FILE;
+ }
+
+ return $gst_debug_fd_hash{$debug_path};
+}
+
+sub gst_debug_close_all
+{
+ my ($file, @files);
+
+ @files = keys %gst_debug_fd_hash;
+ foreach $file (@files)
+ {
+ &gst_file_close ($gst_debug_fd_hash{$file});
+ delete $gst_debug_fd_hash{$file};
+ }
+}
+
+sub gst_debug_print_string_to_file
+{
+ my $debug_file;
+
+ $debug_file = &gst_debug_open_output_file ($_[0]);
+ print $debug_file $_[1];
+}
+
+sub gst_debug_print_log_to_file
+{
+ my ($file, $doc) = @_;
+ my (@buff, $line, $fd);
+
+ $fd = &gst_debug_open_output_file ($file);
+
+ @buff = split ("\n", $doc);
+ foreach $line (@buff)
+ {
+ print $fd "$line\n";
+ }
+}
+
+
+sub gst_debug_print_string
+{
+ if ($gst_debug) { print STDERR $_[0]; }
+ &gst_debug_print_string_to_file ("debug", $_[0]);
+}
+
+
+sub gst_debug_print_line
+{
+ &gst_debug_print_string ($_[0] . "\n");
+}
+
+
+sub gst_debug_print_indent
+{
+ my $indent = $_[0];
+ my $indent_string = "";
+
+ $indent_string = " " x $indent;
+ &gst_debug_print_string ($indent_string);
+}
+
+
+sub gst_debug_print_indented_string
+{
+ my ($indent, @string) = @_;
+
+ &gst_debug_print_indent ($indent);
+ &gst_debug_print_string (@string);
+}
+
+
+sub gst_debug_print_indented_line
+{
+ my $indent = shift @_;
+ my @line = @_;
+
+ &gst_debug_print_indent ($indent);
+ &gst_debug_print_line (@line);
+}
+
+
+sub gst_debug_print_struct
+{
+ foreach $i (@_)
+ {
+ &gst_debug_print_struct_r (0, 0, $i);
+ }
+}
+
+
+sub gst_debug_print_struct_r
+{
+ my ($indent) = $_[0];
+ my $is_hash_value = $_[1];
+ my $a = $_[2];
+ my $type;
+ my @keys;
+ my $elem;
+ my $i;
+
+ $type = ref $a;
+
+ if (!$is_hash_value) { &gst_debug_print_indent ($indent); }
+
+ if ($type eq "SCALAR")
+ {
+ &gst_debug_print_line ($$a);
+ }
+ elsif ($type eq "ARRAY")
+ {
+ &gst_debug_print_line ("[ARRAY]");
+
+ for ($i = 0; $i <= $#$a; $i++)
+ {
+ &gst_debug_print_struct_r ($indent + 1, 0, $$a[$i]);
+ }
+ }
+ elsif ($type eq "HASH")
+ {
+ @keys = sort keys (%$a);
+
+ &gst_debug_print_line ("[HASH]");
+
+ foreach $i (@keys)
+ {
+ &gst_debug_print_indented_string ($indent + !$is_hash_value, $i . " -> ");
+ &gst_debug_print_struct_r ($indent + !$is_hash_value + 1, 1, $$a{$i});
+ }
+ }
+ else
+ {
+ &gst_debug_print_line ($a);
+ }
+}
+
+
+$gst_debug_dir_rotation_was_made = 0;
+
+sub gst_debug_rotate_try
+{
+
+ my $debug_file = $_[0];
+ my $debug_tool_dir = &gst_file_get_debug_path () . "/$gst_name";
+
+ # If this is the first debug created by this tool on this invocation,
+ # rotate the debug directories and create a new, empty one.
+
+ if (!$gst_debug_dir_rotation_was_made)
+ {
+ my $i;
+
+ $gst_debug_dir_rotation_was_made = 1;
+
+ if (-e "$debug_tool_dir/9")
+ {
+ &gst_file_rmtree ("$debug_tool_dir/9", 0, 1);
+ }
+
+ for ($i = 8; $i; $i--)
+ {
+ if (-e "$debug_tool_dir/$i")
+ {
+ move ("$debug_tool_dir/$i", "$debug_tool_dir/" . ($i + 1));
+ }
+ }
+
+ &gst_file_create_path ("$debug_tool_dir/1");
+ }
+}
+
+1;
diff --git a/knetworkconf/backends/file.pl.in b/knetworkconf/backends/file.pl.in
new file mode 100644
index 0000000..f3be154
--- /dev/null
+++ b/knetworkconf/backends/file.pl.in
@@ -0,0 +1,934 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Functions for file manipulation. Find, open, read, write, backup, etc.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Arturo Espinosa <arturo@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+use File::Path;
+use File::Copy;
+use File::Temp;
+use Carp;
+
+$SCRIPTSDIR = "@scriptsdir@";
+$FILESDIR = "@filesdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $FILESDIR = "files";
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/general.pl$DOTIN";
+require "$SCRIPTSDIR/report.pl$DOTIN";
+
+
+$GST_FILE_READ = 1;
+$GST_FILE_WRITE = 2;
+
+
+# --- File operations --- #
+
+
+sub gst_file_get_base_path
+{
+ my $path = "/var/cache/setup-tool-backends";
+ chmod (0755, $path);
+ return $path;
+}
+
+
+sub gst_file_get_tmp_path
+{
+ return (&gst_file_get_base_path () . "/tmp");
+}
+
+
+sub gst_file_get_backup_path
+{
+ return (&gst_file_get_base_path () . "/backup");
+}
+
+
+sub gst_file_get_debug_path
+{
+ return (&gst_file_get_base_path (). "/debug");
+}
+
+
+sub gst_file_get_data_path
+{
+ my $path = &gst_file_get_base_path (). "/data";
+ chmod (0755, $path);
+ return $path;
+}
+
+
+# Give a command, and it will put in C locale, some sane PATH values and find
+# the program to run in the path. Redirects stderr to null.
+sub get_cmd_path
+{
+ my ($cmd) = @_;
+ my ($tool_name, @argline, $command, $tool_path);
+
+ ($tool_name, @argline) = split("[ \t]+", $cmd);
+
+ $tool_path = &gst_file_locate_tool ($tool_name);
+ return -1 if ($tool_path eq "");
+
+
+ $command = "$tool_path @argline";
+ $command =~ s/\"/\\\"/g;
+
+ return $command;
+}
+
+sub gst_file_get_cmd_path
+{
+ my ($cmd) = @_;
+
+ my $command = &get_cmd_path ($cmd);
+ return ("LC_ALL=C PATH=\$PATH:/sbin:/usr/sbin $command 2> /dev/null");
+}
+
+# necessary for some programs that output info through stderr
+sub gst_file_get_cmd_path_with_stderr
+{
+ my ($cmd) = @_;
+
+ my $command = &get_cmd_path ($cmd);
+ return ("LC_ALL=C PATH=\$PATH:/sbin:/usr/sbin $command 2>&1");
+}
+
+
+sub gst_file_create_path
+{
+ my ($path, $perms) = @_;
+ $prems = $perms || 0770;
+ my @pelem;
+
+ $path =~ tr/\///s;
+ @pelem = split(/\//, $path); # 'a/b/c/d/' -> 'a', 'b', 'c', 'd', ''
+
+ for ($path = ""; @pelem; shift @pelem)
+ {
+ $path = "$path$pelem[0]";
+ mkdir($path, $perms);
+ $path = "$path/";
+ }
+
+ &gst_report_enter ();
+ &gst_report ("file_create_path", $_[0]);
+ &gst_report_leave ();
+}
+
+
+sub gst_file_create_path_for_file
+{
+ my ($path, $perms) = @_;
+ $prems = $perms || 0770;
+ my @pelem;
+
+ $path =~ tr/\///s;
+ @pelem = split(/\//, $path); # 'a/b/c/d/' -> 'a', 'b', 'c', 'd', ''
+
+ for ($path = ""; @pelem; shift @pelem)
+ {
+ if ($pelem[1] ne "")
+ {
+ $path = "$path$pelem[0]";
+ mkdir($path, $perms);
+ $path = "$path/";
+ }
+ }
+
+ &gst_report_enter ();
+ &gst_report ("file_create_path", $_[0]);
+ &gst_report_leave ();
+}
+
+
+$gst_file_backup_dir_rotation_was_made = 0;
+
+# If this is the first backup created by this tool on this invocation,
+# rotate the backup directories and create a new, empty one.
+sub gst_file_backup_rotate_dirs
+{
+ my $backup_tool_dir = $_[0];
+
+ &gst_report_enter ();
+
+ if (!$gst_file_backup_dir_rotation_was_made)
+ {
+ my $i;
+
+ $gst_file_backup_dir_rotation_was_made = 1;
+ if (-e "$backup_tool_dir/9")
+ {
+ if (-s "$backup_tool_dir/9")
+ {
+ unlink ("$backup_tool_dir/9");
+ }
+ else
+ {
+ &gst_file_rmtree ("$backup_tool_dir/9");
+ }
+ }
+
+ for ($i = 8; $i; $i--)
+ {
+ if (stat ("$backup_tool_dir/$i"))
+ {
+ move ("$backup_tool_dir/$i", "$backup_tool_dir/" . ($i+1));
+ }
+ }
+
+ if (!stat ("$backup_tool_dir/First"))
+ {
+ &gst_file_create_path ("$backup_tool_dir/First");
+ &gst_file_run ("ln -s First $backup_tool_dir/1");
+ }
+ else
+ {
+ &gst_file_create_path_for_file ("$backup_tool_dir/1/");
+ }
+
+ &gst_report ("file_backup_rotate", $backup_tool_dir);
+ }
+
+ &gst_report_enter ();
+}
+
+sub gst_file_backup
+{
+ my $backup_file = $_[0];
+ my $backup_tool_dir;
+
+ &gst_report_enter ();
+
+ $backup_tool_dir = &gst_file_get_backup_path () . "/$gst_name/";
+
+ &gst_file_backup_rotate_dirs ($backup_tool_dir);
+
+ # If the file hasn't already been backed up on this invocation, copy the
+ # file to the backup directory.
+
+ if (!stat ("$backup_tool_dir/1/$backup_file"))
+ {
+ &gst_file_create_path_for_file ("$backup_tool_dir/1/$backup_file");
+ copy ($backup_file, "$backup_tool_dir/1/$backup_file");
+ &gst_report ("file_backup_success", $backup_tool_dir);
+ }
+
+ &gst_report_leave ();
+}
+
+# Return 1/0 depending on file existance.
+sub gst_file_exists
+{
+ my ($file) = @_;
+
+ return (-f "$gst_prefix/$file")? 1: 0;
+}
+
+sub gst_file_open_read_from_names
+{
+ local *FILE;
+ my $fname = "";
+
+ &gst_report_enter ();
+
+ foreach $name (@_)
+ {
+ if (open (FILE, "$gst_prefix/$name"))
+ {
+ $fname = $name;
+ last;
+ }
+ }
+
+ (my $fullname = "$gst_prefix/$fname") =~ tr/\//\//s; # '//' -> '/'
+
+ if ($fname eq "")
+ {
+ &gst_report ("file_open_read_failed", "@_");
+ return undef;
+ }
+
+ &gst_report ("file_open_read_success", $fullname);
+ &gst_report_leave ();
+
+ return *FILE;
+}
+
+
+sub gst_file_open_write_from_names
+{
+ local *FILE;
+ my $name;
+ my $fullname;
+
+ &gst_report_enter ();
+
+ # Find out where it lives.
+
+ foreach $elem (@_) { if (stat($elem) ne "") { $name = $elem; last; } }
+
+ if ($name eq "")
+ {
+ $name = $_[0];
+ (my $fullname = "$gst_prefix/$name") =~ tr/\//\//s;
+ &gst_report ("file_open_write_create", "@_", $fullname);
+ }
+ else
+ {
+ (my $fullname = "$gst_prefix/$name") =~ tr/\//\//s;
+ &gst_report ("file_open_write_success", $fullname);
+ }
+
+ ($name = "$gst_prefix/$name") =~ tr/\//\//s; # '//' -> '/'
+ &gst_file_create_path_for_file ($name);
+
+ # Make a backup if the file already exists - if the user specified a prefix,
+ # it might not.
+
+ if (stat ($name))
+ {
+ &gst_file_backup ($name);
+ }
+
+ &gst_report_leave ();
+
+ # Truncate and return filehandle.
+
+ if (!open (FILE, ">$name"))
+ {
+ &gst_report ("file_open_write_failed", $name);
+ return undef;
+ }
+
+ return *FILE;
+}
+
+sub gst_file_open_filter_write_from_names
+{
+ local *INFILE;
+ local *OUTFILE;
+ my ($filename, $name, $elem);
+
+ &gst_report_enter ();
+
+ # Find out where it lives.
+
+ foreach $coin (@_)
+ {
+ if (-e $coin) { $name = $coin; last; }
+ }
+
+ if (! -e $name)
+ {
+ # If we couldn't locate the file, and have no prefix, give up.
+
+ # If we have a prefix, but couldn't locate the file relative to '/',
+ # take the first name in the array and let that be created in $prefix.
+
+ if ($prefix eq "")
+ {
+ &gst_report ("file_open_filter_failed", "@_");
+ return(0, 0);
+ }
+ else
+ {
+ $name = $_[0];
+ (my $fullname = "$gst_prefix/$name") =~ tr/\//\//s;
+ &gst_report ("file_open_filter_create", "@_", $fullname);
+ }
+ }
+ else
+ {
+ (my $fullname = "$gst_prefix/$name") =~ tr/\//\//s;
+ &gst_report ("file_open_filter_success", $name, $fullname);
+ }
+
+ ($filename) = $name =~ /.*\/(.+)$/;
+ ($name = "$gst_prefix/$name") =~ tr/\//\//s; # '//' -> '/'
+ &gst_file_create_path_for_file ($name);
+
+ # Make a backup if the file already exists - if the user specified a prefix,
+ # it might not.
+
+ if (-e $name)
+ {
+ &gst_file_backup ($name);
+ }
+
+ # Return filehandles. Make a copy to use as filter input. It might be
+ # invalid (no source file), in which case the caller should just write to
+ # OUTFILE without bothering with INFILE filtering.
+
+ my $tmp_path = &gst_file_get_tmp_path ();
+
+ &gst_file_create_path ("$tmp_path");
+ unlink ("$tmp_path/$gst_name-$filename");
+ copy ($name, "$tmp_path/$gst_name-$filename");
+
+ open (INFILE, "$tmp_path/$gst_name-$filename");
+
+ if (!open (OUTFILE, ">$name"))
+ {
+ &gst_report ("file_open_filter_failed", $name);
+ return;
+ }
+
+ &gst_report_leave ();
+
+ return (*INFILE, *OUTFILE);
+}
+
+
+sub gst_file_open_write_compressed
+{
+ local *FILE;
+ my ($name, $fullname, $gzip);
+
+ $gzip = &gst_file_locate_tool ("gzip");
+ return undef if (!$gzip);
+
+ &gst_report_enter ();
+
+ # Find out where it lives.
+
+ foreach $elem (@_) { if (stat($elem) ne "") { $name = $elem; last; } }
+
+ if ($name eq "")
+ {
+ $name = $_[0];
+ (my $fullname = "$gst_prefix/$name") =~ tr/\//\//s;
+ &gst_report ("file_open_write_create", "@_", $fullname);
+ }
+ else
+ {
+ (my $fullname = "$gst_prefix/$name") =~ tr/\//\//s;
+ &gst_report ("file_open_write_success", $fullname);
+ }
+
+ ($name = "$gst_prefix/$name") =~ tr/\//\//s; # '//' -> '/'
+ &gst_file_create_path_for_file ($name);
+
+ # Make a backup if the file already exists - if the user specified a prefix,
+ # it might not.
+
+ if (stat ($name))
+ {
+ &gst_file_backup ($name);
+ }
+
+ &gst_report_leave ();
+
+ # Truncate and return filehandle.
+
+ if (!open (FILE, "| $gzip -c > $name"))
+ {
+ &gst_report ("file_open_write_failed", $name);
+ return;
+ }
+
+ return *FILE;
+}
+
+
+sub gst_file_run_pipe
+{
+ my ($cmd, $mode_mask, $stderr) = @_;
+ my ($command);
+ local *PIPE;
+
+ $mode_mask = $GST_FILE_READ if $mode_mask eq undef;
+
+ &gst_report_enter ();
+
+ if ($stderr)
+ {
+ $command = &gst_file_get_cmd_path_with_stderr ($cmd);
+ }
+ else
+ {
+ $command = &gst_file_get_cmd_path ($cmd);
+ }
+
+ if ($command == -1)
+ {
+ &gst_report ("file_run_pipe_failed", $command);
+ &gst_report_leave ();
+ return undef;
+ }
+
+ $command .= " |" if $mode_mask & $GST_FILE_READ;
+ $command = "| $command > /dev/null" if $mode_mask & $GST_FILE_WRITE;
+
+ open PIPE, $command;
+ &gst_report ("file_run_pipe_success", $command);
+ &gst_report_leave ();
+ return *PIPE;
+}
+
+
+sub gst_file_run_pipe_read
+{
+ my ($cmd) = @_;
+
+ return &gst_file_run_pipe ($cmd, $GST_FILE_READ);
+}
+
+sub gst_file_run_pipe_read_with_stderr
+{
+ my ($cmd) = @_;
+
+ return &gst_file_run_pipe ($cmd, $GST_FILE_READ, 1);
+}
+
+sub gst_file_run_pipe_write
+{
+ my ($cmd) = @_;
+
+ return &gst_file_run_pipe ($cmd, $GST_FILE_WRITE);
+}
+
+
+sub gst_file_run_backtick
+{
+ my ($cmd, $stderr) = @_;
+ my ($fd, $res);
+
+ if ($stderr)
+ {
+ $fd = &gst_file_run_pipe_read_with_stderr ($cmd);
+ }
+ else
+ {
+ $fd = &gst_file_run_pipe_read ($cmd);
+ }
+
+ $res = join ('', <$fd>);
+ &gst_file_close ($fd);
+
+ return $res;
+}
+
+
+sub gst_file_close
+{
+ my ($fd) = @_;
+
+ close $fd if (ref \$fd eq "GLOB");
+}
+
+
+sub gst_file_remove
+{
+ my ($name) = @_;
+
+ &gst_report_enter ();
+ &gst_report ("file_remove", $name);
+
+ if (stat ($name))
+ {
+ &gst_file_backup ($name);
+ }
+
+ unlink $name;
+ &gst_report_leave ();
+}
+
+sub gst_file_rmtree
+{
+ my($roots, $verbose, $safe) = @_;
+ my(@files);
+ my($count) = 0;
+ $verbose ||= 0;
+ $safe ||= 0;
+
+ if ( defined($roots) && length($roots) ) {
+ $roots = [$roots] unless ref $roots;
+ }
+ else {
+ carp "No root path(s) specified\n";
+ return 0;
+ }
+
+ my($root);
+ foreach $root (@{$roots}) {
+ $root =~ s#/\z##;
+ (undef, undef, my $rp) = lstat $root or next;
+ $rp &= 07777; # don't forget setuid, setgid, sticky bits
+
+ if ( -d $root ) { # $root used to be _, which is a bug.
+ # this is why we are replicating this function.
+
+ # notabene: 0777 is for making readable in the first place,
+ # it's also intended to change it to writable in case we have
+ # to recurse in which case we are better than rm -rf for
+ # subtrees with strange permissions
+ chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
+ or carp "Can't make directory $root read+writeable: $!"
+ unless $safe;
+
+ local *DIR;
+ if (opendir DIR, $root) {
+ @files = readdir DIR;
+ closedir DIR;
+ }
+ else {
+ carp "Can't read $root: $!";
+ @files = ();
+ }
+
+ # Deleting large numbers of files from VMS Files-11 filesystems
+ # is faster if done in reverse ASCIIbetical order
+ @files = reverse @files if $Is_VMS;
+ ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
+ @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files);
+ $count += &gst_file_rmtree(\@files,$verbose,$safe);
+ if ($safe &&
+ ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
+ print "skipped $root\n" if $verbose;
+ next;
+ }
+ chmod 0777, $root
+ or carp "Can't make directory $root writeable: $!"
+ if $force_writeable;
+ print "rmdir $root\n" if $verbose;
+ if (rmdir $root) {
+ ++$count;
+ }
+ else {
+ carp "Can't remove directory $root: $!";
+ chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
+ or carp("and can't restore permissions to "
+ . sprintf("0%o",$rp) . "\n");
+ }
+ }
+ else {
+ if ($safe &&
+ ($Is_VMS ? !&VMS::Filespec::candelete($root)
+ : !(-l $root || -w $root)))
+ {
+ print "skipped $root\n" if $verbose;
+ next;
+ }
+ chmod 0666, $root
+ or carp "Can't make file $root writeable: $!"
+ if $force_writeable;
+ print "unlink $root\n" if $verbose;
+ # delete all versions under VMS
+ for (;;) {
+ unless (unlink $root) {
+ carp "Can't unlink file $root: $!";
+ if ($force_writeable) {
+ chmod $rp, $root
+ or carp("and can't restore permissions to "
+ . sprintf("0%o",$rp) . "\n");
+ }
+ last;
+ }
+ ++$count;
+ last unless $Is_VMS && lstat $root;
+ }
+ }
+ }
+
+ $count;
+}
+
+# --- Buffer operations --- #
+
+
+# Open $file and put it into @buffer, for in-line editting.
+# \@buffer on success, undef on error.
+
+sub gst_file_buffer_load
+{
+ my ($file) = @_;
+ my @buffer;
+ my $fd;
+
+ &gst_report_enter ();
+ &gst_report ("file_buffer_load", $file);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ return [] unless $fd;
+
+ @buffer = (<$fd>);
+
+ &gst_report_leave ();
+
+ return \@buffer;
+}
+
+# Same with an already open fd.
+sub gst_file_buffer_load_fd
+{
+ my ($fd) = @_;
+ my (@buffer);
+
+ &gst_report_enter ();
+ &gst_report ("file_buffer_load", $file);
+
+ @buffer = (<$fd>);
+
+ &gst_report_leave ();
+
+ return \@buffer;
+}
+
+# Take a $buffer and save it in $file. -1 is error, 0 success.
+
+sub gst_file_buffer_save
+{
+ my ($buffer, $file) = @_;
+ my ($fd, $i);
+
+ &gst_report_enter ();
+ &gst_report ("file_buffer_save", $file);
+
+ foreach $i (@$buffer)
+ {
+ &gst_debug_print_string ("|" . $i);
+ }
+
+ $fd = &gst_file_open_write_from_names ($file);
+ return -1 if !$fd;
+
+ if (@$buffer < 1)
+ {
+ # We want to write single line.
+ # Print only if $buffer is NOT a reference (it'll print ARRAY(0x412493) for example).
+ print $fd $buffer if (!ref ($buffer));
+ }
+
+ else
+ {
+ # Let's print array
+
+ foreach $i (@$buffer)
+ {
+ print $fd $i;
+ }
+ }
+
+ &gst_file_close ($fd);
+
+ &gst_report_leave ();
+
+ return 0;
+}
+
+
+# Erase all empty string elements from the $buffer.
+
+sub gst_file_buffer_clean
+{
+ my $buffer = $_[0];
+ my $i;
+
+ for ($i = 0; $i <= $#$buffer; $i++)
+ {
+ splice (@$buffer, $i, 1) if $$buffer[$i] eq "";
+ }
+}
+
+
+sub gst_file_buffer_join_lines
+{
+ my $buffer = $_[0];
+ my $i;
+
+ for ($i = 0; $i <= $#$buffer; $i++)
+ {
+ while ($$buffer[$i] =~ /\\$/)
+ {
+ chomp $$buffer[$i];
+ chop $$buffer[$i];
+ $$buffer[$i] .= $$buffer[$i + 1];
+ splice (@$buffer, $i + 1, 1);
+ }
+ }
+}
+
+
+# --- Command-line utilities --- #
+
+
+# &gst_file_run (<command line>)
+#
+# Assumes the first word on the command line is the command-line utility
+# to run, and tries to locate it, replacing it with its full path. The path
+# is cached in a hash, to avoid searching for it repeatedly. Output
+# redirection is appended, to make the utility perfectly silent. The
+# preprocessed command line is run, and its exit value is returned.
+#
+# Example: "mkswap /dev/hda3" -> 'PATH=$PATH:/sbin:/usr/sbin /sbin/mkswap /dev/hda3 2>/dev/null >/dev/null'.
+
+sub gst_file_run
+{
+ my ($cmd, $background) = @_;
+ my ($command, $tool_name, $tool_path, @argline);
+
+ &gst_report_enter ();
+
+ $command = &gst_file_get_cmd_path ($cmd);
+ return -1 if $command == -1;
+ $command .= " > /dev/null";
+ $command .= " &" if $background;
+
+ &gst_report ("file_run", $command);
+ &gst_report_leave ();
+
+ # As documented in perlfunc, divide by 256.
+ return (system ($command) / 256);
+}
+
+sub gst_file_run_bg
+{
+ my ($cmd) = @_;
+
+ return &gst_file_run ($cmd, 1);
+}
+
+# &gst_file_locate_tool
+#
+# Tries to locate a command-line utility from a set of built-in paths
+# and a set of user paths (found in the environment). The path (or a negative
+# entry) is cached in a hash, to avoid searching for it repeatedly.
+
+@gst_builtin_paths = ( "/sbin", "/usr/sbin", "/usr/local/sbin",
+ "/bin", "/usr/bin", "/usr/local/bin" );
+
+%gst_tool_paths = ();
+
+sub gst_file_locate_tool
+{
+ my ($tool) = @_;
+ my $found = "";
+ my @user_paths;
+
+ # We don't search absolute paths. Arturo.
+ if ($tool =~ /^\//)
+ {
+ if (! (-x $tool))
+ {
+ &gst_report ("file_locate_tool_failed", $tool);
+ return "";
+ }
+
+ return $tool;
+ }
+
+ &gst_report_enter ();
+
+ $found = $gst_tool_paths{$tool};
+ if ($found eq "0")
+ {
+ # Negative cache hit. At this point, the failure has already been reported
+ # once.
+ return "";
+ }
+
+ if ($found eq "")
+ {
+ # Nothing found in cache. Look for real.
+
+ # Extract user paths to try.
+
+ @user_paths = ($ENV{PATH} =~ /([^:]+):/mg);
+
+ # Try user paths.
+
+ foreach $path (@user_paths)
+ {
+ if (-x "$path/$tool" || -u "$path/$tool") { $found = "$path/$tool"; last; }
+ }
+
+ if (!$found)
+ {
+ # Try builtin paths.
+ foreach $path (@gst_builtin_paths)
+ {
+ if (-x "$path/$tool" || -u "$path/$tool") { $found = "$path/$tool"; last; }
+ }
+ }
+
+ # Report success/failure and update cache.
+
+ if ($found)
+ {
+ $gst_tool_paths{$tool} = $found;
+ &gst_report ("file_locate_tool_success", $tool);
+ }
+ else
+ {
+ $gst_tool_paths{$tool} = "0";
+ &gst_report ("file_locate_tool_failed", $tool);
+ }
+ }
+
+ &gst_report_leave ();
+
+ return ($found);
+}
+
+sub gst_file_tool_installed
+{
+ my ($tool) = @_;
+
+ $tool = &gst_file_locate_tool ($tool);
+ return 0 if $tool eq "";
+ return 1;
+}
+
+sub gst_file_copy
+{
+ my ($orig, $dest) = @_;
+
+ return if (!gst_file_exists ($orig));
+ copy ("$gst_prefix/$orig", "$gst_prefix/$dest");
+}
+
+sub gst_file_get_temp_name
+{
+ my ($prefix) = @_;
+
+ return mktemp ($prefix);
+}
+
+sub gst_file_copy_from_stock
+{
+ my ($orig, $dest) = @_;
+
+ if (!copy ("$FILESDIR/$orig", $dest))
+ {
+ &gst_report ("file_copy_failed", "$FILESDIR/$orig", $dest);
+ return -1;
+ }
+
+ return 0;
+}
+
+1;
diff --git a/knetworkconf/backends/general.pl.in b/knetworkconf/backends/general.pl.in
new file mode 100644
index 0000000..809c77a
--- /dev/null
+++ b/knetworkconf/backends/general.pl.in
@@ -0,0 +1,644 @@
+#!/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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, 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;
diff --git a/knetworkconf/backends/guess_system.sh b/knetworkconf/backends/guess_system.sh
new file mode 100755
index 0000000..e1b5871
--- /dev/null
+++ b/knetworkconf/backends/guess_system.sh
@@ -0,0 +1,1121 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
+# Free Software Foundation, Inc.
+#
+# This file 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+# Please send patches to <autoconf-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# Use $HOST_CC if defined. $CC may point to a cross-compiler
+if test x"$CC_FOR_BUILD" = x; then
+ if test x"$HOST_CC" != x; then
+ CC_FOR_BUILD="$HOST_CC"
+ else
+ if test x"$CC" != x; then
+ CC_FOR_BUILD="$CC"
+ else
+ CC_FOR_BUILD=cc
+ fi
+ fi
+fi
+
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >$dummy.s
+ .globl main
+ .ent main
+main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./$dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+ fi
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ arm32:NetBSD:*:*)
+ echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ SR2?01:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:NetBSD:*:*)
+ echo powerpc-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy \
+ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ sed 's/^ //' << EOF >$dummy.c
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+ rm -f $dummy.c $dummy
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ hppa*:OpenBSD:*:*)
+ echo hppa-unknown-openbsd
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alpha-cray-unicosmk${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ if test -x /usr/bin/objformat; then
+ if test "elf" = "`/usr/bin/objformat`"; then
+ echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
+ exit 0
+ fi
+ fi
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ ld_help_string=`cd /; ld --help 2>&1`
+ ld_supported_emulations=`echo $ld_help_string \
+ | sed -ne '/supported emulations:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported emulations: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_emulations" in
+ *ia64)
+ echo "${UNAME_MACHINE}-unknown-linux"
+ exit 0
+ ;;
+ i?86linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0
+ ;;
+ i?86coff)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0
+ ;;
+ sparclinux)
+ echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
+ exit 0
+ ;;
+ armlinux)
+ echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
+ exit 0
+ ;;
+ elf32arm*)
+ echo "${UNAME_MACHINE}-unknown-linux-gnu"
+ exit 0
+ ;;
+ armelf_linux*)
+ echo "${UNAME_MACHINE}-unknown-linux-gnu"
+ exit 0
+ ;;
+ m68klinux)
+ echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
+ exit 0
+ ;;
+ elf32ppc)
+ # Determine Lib Version
+ cat >$dummy.c <<EOF
+#include <features.h>
+#if defined(__GLIBC__)
+extern char __libc_version[];
+extern char __libc_release[];
+#endif
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#if defined(__GLIBC__)
+ printf("%s %s\n", __libc_version, __libc_release);
+#else
+ printf("unkown\n");
+#endif
+ return 0;
+}
+EOF
+ LIBC=""
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./$dummy | grep 1\.99 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f $dummy.c $dummy
+ echo powerpc-unknown-linux-gnu${LIBC}
+ exit 0
+ ;;
+ esac
+
+ if test "${UNAME_MACHINE}" = "alpha" ; then
+ sed 's/^ //' <<EOF >$dummy.s
+ .globl main
+ .ent main
+ main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ LIBC=""
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./$dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+
+ objdump --private-headers $dummy | \
+ grep ld.so.1 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+ elif test "${UNAME_MACHINE}" = "mips" ; then
+ cat >$dummy.c <<EOF
+#ifdef __cplusplus
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __MIPSEB__
+ printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+ printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld)
+ # or one that does not give us useful --help.
+ # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ # If ld does not provide *any* "supported emulations:"
+ # that means it is gnuoldld.
+ echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+ test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+
+ case "${UNAME_MACHINE}" in
+ i?86)
+ VENDOR=pc;
+ ;;
+ *)
+ VENDOR=unknown;
+ ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i?86:*:5:7*)
+ # Fixed at (any) Pentium or better
+ UNAME_MACHINE=i586
+ if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then
+ echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:*:6*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-qnx-qnx${UNAME_VERSION}
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/knetworkconf/backends/mkinstalldirs b/knetworkconf/backends/mkinstalldirs
new file mode 100755
index 0000000..d2d5f21
--- /dev/null
+++ b/knetworkconf/backends/mkinstalldirs
@@ -0,0 +1,111 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage" 1>&2
+ exit 0
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+case $dirmode in
+ '')
+ if mkdir -p -- . 2>/dev/null; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ fi
+ ;;
+esac
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=""
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# End:
+# mkinstalldirs ends here
diff --git a/knetworkconf/backends/network-conf.in b/knetworkconf/backends/network-conf.in
new file mode 100755
index 0000000..104eb88
--- /dev/null
+++ b/knetworkconf/backends/network-conf.in
@@ -0,0 +1,639 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Network configurator. Designed to be architecture and distribution independent.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Michael Vogt <mvo@debian.org> (Debian Support)
+# Arturo Espinosa <arturo@ximian.com>
+# Grzegorz Golawski <grzegol@pld-linux.org> (PLD Support)
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+# Best viewed with 100 columns of width.
+
+# Configuration files affected:
+#
+# /etc/resolv.conf
+# /etc/host.conf
+# /etc/hosts
+# /etc/sysconfig/network
+# /etc/rc.config
+# /etc/smb.conf
+
+# Running programs affected:
+#
+# smbd
+# nmbd
+# ifconfig: check current interfaces and activate/deactivate.
+
+BEGIN {
+ $SCRIPTSDIR = "@scriptsdir@";
+ if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+ {
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+ }
+
+ require "$SCRIPTSDIR/general.pl$DOTIN";
+ require "$SCRIPTSDIR/platform.pl$DOTIN";
+ require "$SCRIPTSDIR/util.pl$DOTIN";
+ require "$SCRIPTSDIR/file.pl$DOTIN";
+ require "$SCRIPTSDIR/xml.pl$DOTIN";
+ require "$SCRIPTSDIR/network.pl$DOTIN";
+}
+
+# --- Tool information --- #
+
+$name = "network";
+$version = "@VERSION@";
+@platforms = ("redhat-5.2", "redhat-6.0", "redhat-6.1", "redhat-6.2", "redhat-7.0", "redhat-7.1",
+ "redhat-7.2", "redhat-8.0", "redhat-9",
+ "openna-1.0",
+ "mandrake-7.1", "mandrake-7.2", "mandrake-9.0", "mandrake-9.1", "mandrake-9.2",
+ "mandrake-10.0", "mandrake-10.1","mandrake-10.2", "mandriva-2006.0",
+ "mandriva-2006.1", "mandriva-2007.0", "mandriva-2007.1",
+ "yoper-2.2",
+ "blackpanther-4.0",
+ "debian-2.2", "debian-3.0", "debian-3.1", "debian-4.0", "debian-5.0", "debian-testing",
+ "ubuntu-5.04", "ubuntu-5.10", "ubuntu-6.06", "ubuntu-6.10", "ubuntu-7.04", "ubuntu-7.10", "ubuntu-8.04",
+ "suse-7.0", "suse-9.0", "suse-9.1",
+ "turbolinux-7.0", "fedora-1", "fedora-2", "fedora-3", "fedora-4", "fedora-5", "rpath",
+ "pld-1.0", "pld-1.1", "pld-1.99",
+ "conectiva-9", "conectiva-10",
+ "vine-3.0", "vine-3.1",
+ "ark",
+ "slackware-9.1.0", "slackware-10.0.0", "slackware-10.1.0", "slackware-10.2.0",
+ "gentoo", "vlos-1.2", "freebsd-5", "freebsd-6");
+
+$description =<<"end_of_description;";
+ Configures all network parameters and interfaces.
+end_of_description;
+
+$progress_max = 10;
+
+$profile_file = "profiles.xml";
+
+
+# --- XML parsing ---
+
+# Scan XML from standard input to an internal tree.
+sub xml_parse
+{
+ my ($tree, %hash, $elem);
+ # Scan XML to tree.
+
+ $tree = &gst_xml_scan ();
+
+ # Walk the tree recursively and extract configuration parameters.
+ # This is the top level - find and enter the "network" tag.
+
+ while ($elem = shift @$tree)
+ {
+ if ($elem eq "network") { &xml_parse_network (shift @$tree, \%hash); }
+ else { &gst_report ("xml_unexp_tag", $elem); shift @$tree; }
+ }
+
+ return(\%hash);
+}
+
+# <network>...</network>
+
+sub push_unique
+{
+ my ($arr, $val) = @_;
+ my $i;
+
+ foreach $i (@$arr)
+ {
+ return if $i eq $val;
+ }
+
+ push @$arr, $val;
+}
+
+sub xml_parse_network
+{
+ my ($tree, $hash) = @_;
+ my ($elem);
+ my (@searchdomain, @nameserver, @order, %statichost, %interface, %dialing);
+
+ shift @$tree; # Skip attributes.
+
+ while ($elem = shift @$tree)
+ {
+ if ($elem eq "auto") { $$hash{"auto"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "hostname") { $$hash{"hostname"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "gateway") { $$hash{"gateway"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "gatewaydev") { $$hash{"gatewaydev"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "domain") { $$hash{"domain"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "workgroup") { $$hash{"workgroup"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "smbdesc") { $$hash{"smbdesc"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "name") { $$hash{"name"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "description") { $$hash{"description"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "winsserver") { $$hash{"winsserver"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "winsuse") { $$hash{"winsuse"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "smbuse") { $$hash{"smbuse"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "hostmatch") { $$hash{"hostmatch"} = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "nameserver") { &push_unique (\@nameserver, &gst_xml_get_pcdata (shift @$tree)); }
+ elsif ($elem eq "searchdomain") { &push_unique (\@searchdomain, &gst_xml_get_pcdata (shift @$tree)); }
+ elsif ($elem eq "order") { push (@order, &gst_xml_get_pcdata (shift @$tree)); }
+ elsif ($elem eq "statichost") { &xml_parse_statichost (shift @$tree, \%statichost); }
+ elsif ($elem eq "interface") { &gst_network_xml_parse_interface (shift @$tree, \%interface); }
+ elsif ($elem eq "dialing") { &xml_parse_dialing (shift @$tree, \%dialing); }
+ elsif ($elem eq "dialinstalled") { shift @$tree; }
+ elsif ($elem eq "smbinstalled") { shift @$tree; }
+ elsif ($elem eq "smartdhcpcd") { shift @$tree; }
+ elsif ($elem eq "gwdevunsup") { shift @$tree; }
+ elsif ($elem eq "wireless_device") { shift @$tree; }
+ elsif ($elem eq "profiledb") { &xml_parse_profiledb (shift @$tree, $hash); }
+ else { &gst_report ("xml_unexp_tag", $elem); shift @$tree; }
+ }
+
+ $$hash{"order"} = \@order unless $#order < 0;
+ $$hash{"searchdomain"} = \@searchdomain unless $#searchdomain < 0;
+ $$hash{"nameserver"} = \@nameserver unless $#nameserver < 0;
+ $$hash{"statichost"} = \%statichost unless scalar keys %statichost == 0;
+ $$hash{"interface"} = \%interface unless scalar keys %interface == 0;
+ $$hash{"dialing"} = \%dialing unless scalar keys %dialing == 0;
+}
+
+# <network><statichost>...</statichost></network>
+sub xml_parse_statichost
+{
+ my ($tree, $statichost) = @_;
+ my ($ip, @alias, $elem);
+
+ shift @$tree;
+
+ while ($elem = shift @$tree)
+ {
+ if ($elem eq "ip") { $ip = &gst_xml_get_pcdata (shift @$tree); }
+ elsif ($elem eq "alias") { push(@alias, &gst_xml_get_pcdata (shift @$tree)); }
+ else { &gst_report ("xml_unexp_tag", $elem); shift @$tree; }
+ }
+
+ # common regexp for IPv4 and IPv6
+ if ($ip =~ /([0-9a-fA-F\.:])+/)
+ {
+ $$statichost{$ip} = \@alias;
+ }
+}
+
+sub xml_parse_dialing
+{
+ my ($tree, $dialing) = @_;
+ my (%hash, $name, $elem);
+
+ shift @$tree;
+
+ while ($elem = shift @$tree)
+ {
+ $hash{$elem} = &gst_xml_get_pcdata (shift @$tree);
+ }
+
+ $name = $hash{"name"};
+ $$dialing{$name} = \%hash;
+}
+
+# couple of functions for fixing profiles format
+sub fix_profile_modem_iface
+{
+ my ($configuration, $section, $dialing) = @_;
+ my ($s, $key, %h);
+
+ foreach $s (keys %$dialing)
+ {
+ if ($s eq $section)
+ {
+ $h = $$dialing{$s};
+
+ foreach $key (keys %$h)
+ {
+ $$configuration{$key} = $$h{$key};
+ }
+ }
+ }
+}
+
+sub fix_profile_interface_format
+{
+ my ($interface, $dialing) = @_;
+ my (%configuration, $key, $section);
+
+ return if (exists $$interface{"configuration"});
+
+ foreach $key (keys %$interface)
+ {
+ if ($key !~ /^(dev|enabled|hwaddr)$/)
+ {
+ if ($key eq 'wvsection')
+ {
+ &fix_profile_modem_iface (\%configuration, $$interface{$key}, $dialing);
+ $configuration{"section"} = $$interface{$key};
+ }
+ else
+ {
+ $dest_key = $key;
+ $configuration{$key} = $$interface{$key};
+ }
+
+ delete $$interface{$key};
+ }
+ }
+
+ $$interface{"type"} = &gst_network_get_interface_type ($$interface{"dev"});
+
+ if (%configuration)
+ {
+ $$interface{"configuration"} = \%configuration;
+ }
+}
+
+sub fix_profile_format
+{
+ my ($hash) = @_;
+ my ($interfaces, $dialing, $iface);
+
+ $interfaces = $$hash{"interface"};
+ $dialing = $$hash{"dialing"};
+
+ foreach $iface (keys %$interfaces)
+ {
+ &fix_profile_interface_format ($$interfaces{$iface}, $dialing);
+ }
+}
+
+sub xml_parse_profile
+{
+ my ($tree, $hash) = @_;
+ my (%profile);
+
+ &xml_parse_network ($tree, \%profile);
+
+ # We've got to translate the old profiles format
+ &fix_profile_format (\%profile);
+
+ push @{$hash->{"profiledb"}{"profile"}}, \%profile;
+}
+
+sub xml_parse_profiledb
+{
+ my ($tree, $hash) = @_;
+
+ shift @$tree; # Skip attributes.
+
+ while (@$tree)
+ {
+ if ($$tree[0] eq "profile") { &xml_parse_profile ($$tree[1], $hash); }
+ else
+ {
+ &gst_report ("xml_unexp_tag", $$tree[0]);
+ }
+
+ shift @$tree;
+ shift @$tree;
+ }
+}
+
+# --- XML printing --- #
+
+sub xml_print_configuration
+{
+ my ($h) = @_;
+ my @scalar_keys =
+ qw(auto hostname gateway gatewaydev gwdevunsup domain
+ hostmatch workgroup smbdesc winsserver winsuse smbuse
+ smartdhcpcd smbinstalled dialinstalled name);
+ my @array_keys =
+ qw(nameserver searchdomain order);
+
+ # Hostname, domain, search domains, nameservers.
+
+ &gst_xml_print_scalars ($h, @scalar_keys);
+ &gst_xml_print_arrays ($h, @array_keys);
+ &network_xml_print_statichost ($h);
+
+ &xml_print_interfaces ($$h{"interface"});
+}
+
+sub xml_print_profiledb
+{
+ my ($h) = @_;
+
+ &gst_xml_print_vspace ();
+
+ &gst_xml_print_line ("<profiledb>\n");
+ &gst_xml_enter ();
+ foreach $i (@{$$h{"profiledb"}{"profile"}})
+ {
+ gst_xml_print_line ("<profile>\n");
+ gst_xml_enter ();
+
+ &xml_print_configuration ($i);
+
+ gst_xml_leave ();
+ gst_xml_print_line ("</profile>\n");
+ }
+ gst_xml_leave ();
+ gst_xml_print_line ("</profiledb>\n");
+}
+
+sub xml_print_interfaces
+{
+ my ($h) = @_;
+ my ($dev, $type);
+
+ foreach $dev (keys %$h)
+ {
+ if ($$h{$dev}{"type"})
+ {
+ $type = $$h{$dev}{"type"};
+ delete $$h{$dev}{"type"};
+ }
+ else
+ {
+ $type = &gst_network_get_interface_type ($dev);
+ }
+
+ &gst_xml_print_vspace ();
+ &gst_xml_print_line ("<interface type='$type'>");
+ &gst_xml_enter ();
+ &gst_xml_print_hash ($$h{$dev});
+
+ &gst_xml_leave ();
+ &gst_xml_print_line ("</interface>");
+ }
+}
+
+sub xml_print
+{
+ my ($h) = @_;
+
+ &gst_xml_print_begin ();
+
+ &xml_print_configuration ($h);
+ &xml_print_profiledb ($h);
+
+ &gst_xml_print_end ();
+}
+
+
+# Reading profiles
+sub read_profiledb
+{
+ my ($hash) = @_;
+ my ($path);
+ my ($tree);
+
+ $path = gst_file_get_data_path () . "/" . $main::tool->{"name"} . "/";
+ chmod (0755, $path);
+ chmod (0644, $path . $profile_file);
+
+ $tree = &gst_xml_scan ($path . $profile_file, $tool);
+ if ($tree && scalar @$tree)
+ {
+ if ($$tree[0] eq 'profiledb')
+ {
+ xml_parse_profiledb ($$tree[1], $hash);
+ }
+ else
+ {
+ gst_report ('xml_unexp_tag', $$tree[0]);
+ }
+ }
+}
+
+# Writing profiles
+sub write_profiledb
+{
+ my ($hash) = @_;
+ my $profiledb = $hash->{'profiledb'};
+ my $path = &gst_file_get_data_path () . "/" . $main::tool->{'name'} . "/";
+ chmod (0755, $path);
+
+ if ($profiledb) {
+ # Write our profiles.
+ my $fh = &gst_file_open_write_from_names ($path . $profile_file);
+ if ($fh)
+ {
+ local *STDOUT = $fh;
+ &xml_print_profiledb ($hash);
+ close ($fh);
+
+ delete $hash->{'profiledb'};
+ }
+ }
+ else
+ {
+ gst_file_remove ($path . $profile_file);
+ }
+
+ chmod (0644, $path . $profile_file);
+}
+
+
+# Top-level actions.
+sub get
+{
+ my $hash;
+
+ # network interface stuff
+ $hash = &gst_network_conf_get ();
+ &read_profiledb (\%$hash);
+ &gst_network_ensure_loopback ($hash);
+
+ &gst_report_end ();
+ &xml_print ($hash);
+}
+
+
+sub set
+{
+ my $hash;
+
+ $hash = &xml_parse ();
+ &write_profiledb ($hash);
+ &gst_network_conf_set ($hash);
+ &gst_report_end ();
+}
+
+sub set_profile
+{
+ my ($tool, $profile_name) = @_;
+ my ($hash, $profiles, $profile);
+
+ &read_profiledb (\%$hash);
+ $profiles = $$hash{"profiledb"}{"profile"};
+
+ foreach $profile (@$profiles)
+ {
+ if ($$profile{"name"} eq $profile_name)
+ {
+ &gst_network_conf_set ($profile);
+ }
+ }
+
+ &gst_report_end ();
+}
+
+sub save_profiles
+{
+ my $hash;
+
+ $hash = &xml_parse ();
+ &write_profiledb ($hash);
+ &gst_report_end ();
+}
+
+
+# --- Filter config: XML in, XML out --- #
+
+
+sub filter
+{
+ my $hash;
+
+ $hash = &xml_parse ();
+ &gst_report_end ();
+ &xml_print ($hash);
+}
+
+sub enable_iface
+{
+ my ($tool, $iface, $enabled) = @_;
+ my (%dist_attrib, $iface_set);
+ my %hash = ("configuration" => {"file" => $iface});
+
+ %dist_attrib = &gst_network_get_interface_replace_table ();
+ $iface_set = $dist_attrib{"iface_set"};
+ &$iface_set (\%hash, undef, $enabled, 1);
+
+ # small hack for ensuring that the interface is really down
+ # when messing ifup/ifdown/ifconfig calls
+ if ($enabled == 0)
+ {
+ gst_file_run ("ifconfig $iface down");
+ &drop_dhcp_connection ($iface);
+ &drop_pppd_connection ($iface);
+ }
+
+ # Don't forget to do gst_end when the reports are over!
+ &gst_report_end ();
+ # XML output would come here, but this directive returns no XML.
+}
+
+sub enable_iface_with_config
+{
+ my ($tool) = @_;
+ my ($tree, $hash, $ret, $str);
+
+ # Scan XML to tree.
+ $tree = &gst_xml_scan ();
+
+ if (shift @$tree eq "interface")
+ {
+ $hash = &gst_network_xml_parse_interface (shift @$tree);
+ }
+
+ $ret = &gst_network_enable_iface_with_config ($hash);
+ &gst_report_end ();
+
+ &gst_xml_print_begin ("enable-iface");
+ &gst_xml_print_pcdata ("success", ($ret == 0) ? "1" : "0");
+ &gst_xml_print_end ("enable-iface");
+}
+
+sub list_ifaces
+{
+ my ($tool) = @_;
+ my ($ifaces, $iface, @arr);
+
+ $ifaces = &gst_network_interfaces_get_info ();
+
+ foreach $iface (keys %$ifaces)
+ {
+ push @arr, $$ifaces{$iface};
+ }
+
+ &gst_report_end ();
+ &gst_xml_print_begin ("network-ifaces");
+ &gst_xml_print_structure (\@arr, "interface");
+ &gst_xml_print_end ("network-ifaces");
+}
+
+sub detect_modem
+{
+ my ($tool) = @_;
+ my ($device);
+
+ $device = &gst_network_autodetect_modem ();
+ &gst_report_end ();
+
+ &gst_xml_print_begin ("network-modem-device");
+ &gst_xml_print_pcdata ("device", $device) if ($device ne undef);
+ &gst_xml_print_end ("network-modem-device");
+}
+
+sub detect_essids
+{
+ my ($tool, $iface) = @_;
+ my (@essids);
+
+ $essids = &gst_network_detect_essids ($iface);
+ &gst_report_end ();
+
+ &gst_xml_print_begin ("essids");
+ &gst_xml_print_structure ($essids, "network");
+ &gst_xml_print_end ("essids");
+}
+
+sub set_gateway
+{
+ my ($tool, $iface, $address) = @_;
+
+ &gst_network_route_set_default_gw ($iface, $address);
+ &gst_report_end ();
+}
+
+# --- Main --- #
+
+# get, set and filter are special cases that don't need more parameters than a ref to their function.
+# Read general.pl.in:gst_run_directive to know about the format of this hash.
+
+$directives = {
+ "get" => [ \&get, [], "" ],
+ "set" => [ \&set, [], "" ],
+ "filter" => [ \&filter, [], "" ],
+ "list_ifaces" => [ \&list_ifaces, [],
+ "List interfaces and active/inactive status." ],
+ "save_profiles" => [ \&save_profiles, [], "Save the profiles list" ],
+ "set_profile" => [ \&set_profile, [ "profile_name" ],
+ "Set a profile as the default configuration" ],
+ "enable_iface" => [ \&enable_iface, [ "interface", "enabled" ],
+ "Immediatly enable or disable a given interface. " .
+ "interface is the file tag value, enabled is 1 or 0." ],
+ "enable_iface_with_config" => [ \&enable_iface_with_config, [],
+ "Enable an interface with a given configuration" ],
+ "detect_modem" => [ \&detect_modem, [], "Detects the modem device." ],
+ "detect_essids" => [ \&detect_essids, [ "interface" ], "Detects active wireless networks" ],
+ "set_gateway" => [ \&set_gateway, [ "interface", "address" ], "Sets the default gateway" ]
+};
+
+$tool = &gst_init ($name, $version, $description, $directives, @ARGV);
+&gst_platform_ensure_supported ($tool, @platforms);
+&gst_run ($tool);
diff --git a/knetworkconf/backends/network.pl.in b/knetworkconf/backends/network.pl.in
new file mode 100644
index 0000000..0e8b12c
--- /dev/null
+++ b/knetworkconf/backends/network.pl.in
@@ -0,0 +1,6605 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Common network stuff for the ximian-setup-tools backends.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Arturo Espinosa <arturo@ximian.com>
+# Michael Vogt <mvo@debian.org> - Debian 2.[2|3] support.
+# David Lee Ludwig <davidl@wpi.edu> - Debian 2.[2|3] support.
+# Grzegorz Golawski <grzegol@pld-linux.org> - PLD support
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+use Socket;
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/general.pl$DOTIN";
+require "$SCRIPTSDIR/file.pl$DOTIN";
+require "$SCRIPTSDIR/parse.pl$DOTIN";
+require "$SCRIPTSDIR/replace.pl$DOTIN";
+require "$SCRIPTSDIR/service.pl$DOTIN";
+require "$SCRIPTSDIR/util.pl$DOTIN";
+require "$SCRIPTSDIR/xml.pl$DOTIN";
+require "$SCRIPTSDIR/process.pl$DOTIN";
+
+
+# Shared XML printing function
+sub network_xml_print_statichost
+{
+ my ($h) = $_[0];
+ my ($statichost, $i, $j, $val);
+
+ &gst_xml_print_vspace ();
+ foreach $i (keys %{$$h{"statichost"}})
+ {
+ $statichost = $ {$$h{"statichost"}}{$i};
+ &gst_xml_container_enter ("statichost");
+ $val = &gst_xml_quote ($i);
+ &gst_xml_print_pcdata ("ip", $val);
+ foreach $j (@$statichost)
+ {
+ $val = &gst_xml_quote ($j);
+ &gst_xml_print_pcdata ("alias", $val);
+ }
+ &gst_xml_container_leave ("statichost");
+ }
+}
+
+sub gst_network_get_linux_wireless_ifaces
+{
+ my ($fd, $line);
+ my (@ifaces, $command);
+
+ $command = &gst_file_get_cmd_path ("iwconfig");
+ open $fd, "$command |";
+ return @ifaces if $fd eq undef;
+
+ while (<$fd>)
+ {
+ if (/^([a-zA-Z0-9]+)[\t ].*$/)
+ {
+ push @ifaces, $1;
+ }
+ }
+
+ &gst_file_close ($fd);
+
+ &gst_report_leave ();
+ return \@ifaces;
+}
+
+sub gst_network_get_freebsd_wireless_ifaces
+{
+ my ($fd, $line, $iface);
+ my (@ifaces, $command);
+
+ $command = &gst_file_get_cmd_path ("iwconfig");
+ open $fd, "$command |";
+ return @ifaces if $fd eq undef;
+
+ while (<$fd>)
+ {
+ if (/^([a-zA-Z]+[0-9]+):/)
+ {
+ $iface = $1;
+ }
+
+ if (/media:.*wireless.*/i)
+ {
+ push @ifaces, $iface;
+ }
+ }
+
+ &gst_file_close ($fd);
+ &gst_report_leave ();
+
+ return \@ifaces;
+}
+
+# Returns an array with the wireless devices found
+sub gst_network_get_wireless_ifaces
+{
+ my ($plat) = $$tool{"system"};
+
+ return &gst_network_get_linux_wireless_ifaces if ($plat eq "Linux");
+ return &gst_network_get_freebsd_wireless_ifaces if ($plat eq "FreeBSD");
+}
+
+# set of functions for enabling an interface
+sub gst_network_config_wireless
+{
+ my ($hash, $dev, $command_iwconfig, $command_ifconfig) = @_;
+ my ($essid, $key, $command);
+
+ $essid = $$hash{"configuration"}{"essid"};
+ $key = $$hash{"configuration"}{"key"};
+ $key_type = $$hash{"configuration"}{"key_type"};
+
+ if ($essid)
+ {
+ $command = $command_iwconfig if ($$tool{"system"} eq "Linux");
+ $command = $command_ifconfig if ($$tool{"system"} eq "FreeBSD");
+
+ $command .= " $dev";
+ $command .= " essid '$essid'" if ($essid);
+
+ if ($key)
+ {
+ $key = &gst_network_get_full_key ($key, $key_type);
+ $command .= " key '$key'";
+ }
+ else
+ {
+ $command .= " key off";
+ }
+
+ &gst_file_run ($command);
+ }
+}
+
+sub gst_network_enable_iface
+{
+ my ($hash, $dev, $command_ifconfig) = @_;
+ my ($address, $netmask, $bootproto, $remote_address);
+
+ $address = $$hash{"configuration"}{"address"};
+ $netmask = $$hash{"configuration"}{"netmask"};
+ $bootproto = $$hash{"configuration"}{"bootproto"};
+ $remote_address = $$hash{"configuration"}{"remote_address"};
+
+ if ($bootproto eq "dhcp")
+ {
+ if (&gst_file_locate_tool ("dhclient3"))
+ {
+ $command = "dhclient3 -pf /var/run/dhclient.$dev.pid $dev";
+ }
+ elsif (&gst_file_locate_tool ("dhclient"))
+ {
+ $command = "dhclient -pf /var/run/dhclient.$dev.pid -e $dev";
+ }
+ else
+ {
+ $command = "dhcpcd -n $dev";
+ }
+ }
+ else
+ {
+ $command = $command_ifconfig;
+ $command .= " $dev";
+ $command .= " $address" if ($address);
+ $command .= " netmask $netmask" if ($netmask);
+ $command .= " dstaddr $remote_address" if ($remote_address);
+ $command .= " up";
+ }
+
+ return &gst_file_run ($command);
+}
+
+sub gst_network_get_chat_file
+{
+ my ($hash) = @_;
+ my ($volume, $phone_number, $external_line, $dial_command);
+ my ($dial, $tmp_file, $filename, $arr);
+
+ $volume = $$hash{"configuration"}{"volume"};
+ $phone_number = $$hash{"configuration"}{"phone_number"};
+ $external_line = $$hash{"configuration"}{"external_line"};
+ $dial_command = $$hash{"configuration"}{"dial_command"};
+
+ $filename = gst_file_get_temp_name ("network-admin-chat-script-XXXXXXXXX");
+ $tmp_file = "/tmp/$filename";
+
+ $dial = $dial_command;
+ $dial .= $external_line . "W" if ($external_line);
+ $dial .= $phone_number;
+
+ &gst_network_create_pppscript ($tmp_file);
+ chmod (0600, $tmp_file);
+ &gst_replace_chat ($tmp_file, "atd[tp][0-9wW]+", $dial);
+ &gst_network_set_modem_volume ($tmp_file, $volume);
+
+
+ return $tmp_file;
+}
+
+sub gst_network_enable_modem
+{
+ my ($hash, $dev, $command_pppd, $command_chat) = @_;
+ my ($config, $chat_file, $command, $ret);
+
+ $config = $$hash{"configuration"};
+ $chat_file = &gst_network_get_chat_file ($hash);
+
+ $command = $command_pppd;
+ $command .= " " . $$config{"serial_port"};
+ $command .= " debug" if ($$config{"debug"});
+ $command .= ($$config{"noauth"}) ? " noauth" : " auth";
+ $command .= ($$config{"persist"}) ? " persist" : " nopersist";
+ $command .= ($$config{"serial_hwctl"}) ? " crtscts" : " nocrtscts";
+ $command .= ($$config{"set_default_gw"}) ? " defaultroute" : " nodefaultroute";
+ $command .= " usepeerdns" if ($$config{"update_dns"});
+ $command .= " user " . $$config{"login"};
+ $command .= " connect \'$command_chat -v -f $chat_file\'";
+
+ $ret = &gst_file_run ($command);
+
+ return $ret;
+}
+
+sub gst_network_enable_isdn
+{
+ my ($hash, $dev, $command_pppd) = @_;
+ my ($config, $command);
+
+ $config = $$hash{"configuration"};
+
+ $command = $command_pppd;
+ $command .= " debug" if ($$config{"debug"});
+ $command .= ($$config{"noauth"}) ? " noauth" : " auth";
+ $command .= ($$config{"persist"}) ? " persist" : " nopersist";
+ $command .= ($$config{"serial_hwctl"}) ? " crtscts" : " nocrtscts";
+ $command .= ($$config{"set_default_gw"}) ? " defaultroute" : " nodefaultroute";
+ $command .= " usepeerdns" if ($$config{"update_dns"});
+ $command .= " sync plugin userpass.so ipcp-accept-local ipcp-accept-remote";
+ $command .= " plugin capiplugin.so";
+ $command .= " /dev/null";
+ $command .= " user " . $$config{"login"};
+ $command .= " number " . $$config{"phone_number"};
+
+ return &gst_file_run ($command);
+}
+
+sub drop_dhcp_connection
+{
+ my ($dev) = @_;
+ &gst_process_kill_by_pidfile ("dhclient.$dev.pid");
+ &gst_process_kill_by_pidfile ("/etc/dhcpc/dhcpcd-$dev.pid");
+}
+
+sub drop_pppd_connection
+{
+ my ($dev) = @_;
+ &gst_process_kill_by_pidfile ("$dev.pid");
+}
+
+sub gst_network_enable_iface_with_config
+{
+ my ($hash) = @_;
+ my ($command_ifconfig, $command_iwconfig);
+ my ($command_pppd, $command_chat);
+ my ($dev, $command, $ret);
+
+ $command_ifconfig = "ifconfig";
+ $command_iwconfig = "iwconfig";
+ $command_pppd = "pppd";
+ $command_chat = gst_file_locate_tool ("chat");
+
+ $dev = $$hash{"dev"};
+
+ $command = "$command_ifconfig $dev down";
+ $ret = &gst_file_run ($command);
+
+ &drop_dhcp_connection ($dev);
+ &drop_pppd_connection ($dev);
+
+ if (exists ($$hash{"configuration"}))
+ {
+ if (exists ($$hash{"configuration"}{"phone_number"}))
+ {
+ $login = $$hash{"configuration"}{"login"};
+ $pw = $$hash{"configuration"}{"password"};
+
+ &gst_network_set_pap_passwd ("/etc/ppp/pap-secrets", $login, $pw);
+ &gst_network_set_pap_passwd ("/etc/ppp/chap-secrets", $login, $pw);
+
+ if (&gst_network_check_pppd_plugin ("capiplugin"))
+ {
+ $ret = &gst_network_enable_isdn ($hash, $dev, $command_pppd);
+ }
+ else
+ {
+ $ret = &gst_network_enable_modem ($hash, $dev, $command_pppd, $command_chat);
+ }
+ }
+ else
+ {
+ # if it's a wireless interface, put first the essid
+ &gst_network_config_wireless ($hash, $dev, $command_iwconfig, $command_ifconfig);
+ $ret = &gst_network_enable_iface ($hash, $dev, $command_ifconfig);
+ }
+ }
+
+ return $ret;
+}
+
+# Tries to detect modem in a closed list of devices
+sub gst_network_autodetect_modem
+{
+ my (@arr);
+
+ if ($$tool{"system"} eq "Linux")
+ {
+ @arr = ("/dev/modem", "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3");
+
+ $pid = `pidof pppd 2>/dev/null`;
+
+ if ($pid =~ /\d/) {
+ return;
+ }
+ }
+ elsif ($$tool{"system"} eq "FreeBSD")
+ {
+ @arr = ("/dev/modem", "/dev/cuaa0", "/dev/cuaa1", "/dev/cuaa2", "/dev/cuaa3");
+ }
+
+ foreach $tty (@arr) {
+ $temp = `pppd lcp-max-configure 1 nodetach noauth nocrtscts $tty connect \"chat -t1 \'\' AT OK\" 2>/dev/null`;
+
+ if ($temp =~ /established/) {
+ return $tty;
+ }
+ }
+}
+
+# Parse <interface>...</interface>. Put here so it can be shared with internetsharing.
+sub gst_network_xml_parse_interface_config
+{
+ my ($tree) = @_;
+ my (%config);
+
+ shift @$tree;
+
+ while ($elem = shift @$tree)
+ {
+ $config{$elem} = &gst_xml_get_pcdata (shift @$tree);
+ }
+
+ return \%config;
+}
+
+sub gst_network_xml_parse_interface
+{
+ my ($tree, $interface) = @_;
+ my (%hash, $aux, $dev, $elem);
+
+ shift @$tree;
+
+ while ($elem = shift @$tree)
+ {
+ if ($elem eq "configuration")
+ {
+ $aux = &gst_network_xml_parse_interface_config (shift @$tree);
+ $hash{$elem} = $aux if ($aux ne undef);
+ }
+ else
+ {
+ $hash{$elem} = &gst_xml_get_pcdata (shift @$tree);
+ }
+ }
+
+ if (($hash{"configuration"} ne undef) &&
+ ($hash{"configuration"}{"file"} ne undef))
+ {
+ $dev = $hash{"configuration"}{"file"};
+ }
+ else
+ {
+ $dev = &gst_network_get_file (\%hash);
+ $hash{"configuration"}{"file"} = $dev if ($hash{"configuration"} ne undef);
+ }
+
+ $$interface{$dev} = \%hash;
+ return \%hash;
+}
+
+# Expects something like "132.248.10.2" and returns 4 bytes.
+sub gst_network_ipv4_str2vec
+{
+ my ($str) = @_;
+
+ return pack ('C4', split ('\.', $str));
+}
+
+# Converse
+sub gst_network_ipv4_vec2str
+{
+ my ($vec) = @_;
+
+ return join ('.', unpack ('C4', $vec));
+}
+
+# Gets the subnet, in bitmap.
+sub gst_network_ipv4_calc_subnet_vec
+{
+ my ($addr, $mask) = @_;
+ my ($addrvec, $maskvec);
+
+ $addrvec = &gst_network_ipv4_str2vec ($addr);
+ $maskvec = &gst_network_ipv4_str2vec ($mask);
+
+ return $addrvec & $maskvec;
+}
+
+# What you're looking for.
+sub gst_network_ipv4_calc_subnet
+{
+ my ($addr, $mask) = @_;
+
+ return &gst_network_ipv4_vec2str (&gst_network_ipv4_calc_subnet_vec);
+}
+
+# The broadcast, bitmap.
+sub gst_network_ipv4_calc_bcast_vec
+{
+ my ($addr, $mask) = @_;
+
+ $addrvec = &gst_network_ipv4_str2vec ($addr);
+ $maskvec = &gst_network_ipv4_str2vec ($mask);
+
+ return $addrvec | ~$maskvec;
+}
+
+# And this returning the quad-dot notation.
+sub gst_network_ipv4_calc_bcast
+{
+ my ($addr, $mask) = @_;
+
+ return &gst_network_ipv4_vec2str (&gst_network_ipv4_calc_bcast_vec);
+}
+
+
+# Selects a ping command, which must ping just twice, with
+# one second interval, returning numeric IPs to the given
+# broadcast address.
+sub gst_network_get_broadcast_ping_cmd
+{
+ my ($bcast) = @_;
+ my ($tool_ping);
+
+ my %cmd_map =
+ (
+ "debian-2.2" => "ping -c 2 -i 1 -n $bcast",
+ "redhat-6.2" => "ping -c 2 -i 1 -n -b $bcast"
+ );
+ my %dist_map =
+ (
+ "redhat-6.0" => "redhat-6.2",
+ "redhat-6.1" => "redhat-6.2",
+ "redhat-6.2" => "redhat-6.2",
+ "redhat-7.0" => "redhat-6.2",
+ "redhat-7.1" => "redhat-6.2",
+ "redhat-7.2" => "redhat-6.2",
+ "redhat-8.0" => "redhat-6.2",
+ "redhat-9" => "redhat-6.2",
+ "openna-1.0" => "redhat-6.2",
+ "debian-2.2" => "debian-2.2",
+ "debian-3.0" => "debian-2.2",
+ "debian-3.1" => "debian-2.2",
+ "debian-4.0" => "debian-2.2",
+ "debian-5.0" => "debian-2.2",
+ "debian-testing" => "debian-2.2",
+ "ubuntu-5.04" => "debian-2.2",
+ "ubuntu-5.10" => "debian-2.2",
+ "ubuntu-6.06" => "debian-2.2",
+ "ubuntu-6.10" => "debian-2.2",
+ "ubuntu-7.04" => "debian-2.2",
+ "ubuntu-7.10" => "debian-2.2",
+ "ubuntu-8.04" => "debian-2.2",
+ "mandrake-7.1" => "debian-2.2",
+ "mandrake-7.2" => "debian-2.2",
+ "mandrake-9.0" => "debian-2.2",
+ "mandrake-9.1" => "debian-2.2",
+ "mandrake-9.2" => "debian-2.2",
+ "mandrake-10.0" => "debian-2.2",
+ "mandrake-10.1" => "redhat-6.2",
+ "mandrake-10.2" => "redhat-6.2",
+ "mandriva-2006.0" => "redhat-6.2",
+ "mandriva-2006.1" => "redhat-6.2",
+ "mandriva-2007.0" => "redhat-6.2",
+ "mandriva-2007.1" => "redhat-6.2",
+ "yoper-2.2" => "redhat-6.2",
+ "blackpanther-4.0" => "debian-2.2",
+ "suse-7.0" => "debian-2.2",
+ "suse-9.0" => "redhat-6.2",
+ "suse-9.1" => "redhat-6.2",
+ "pld-1.0" => "redhat-6.2",
+ "pld-1.1" => "redhat-6.2",
+ "pld-1.99" => "redhat-6.2",
+ "conectiva-9" => "debian-2.2",
+ "conectiva-10" => "debian-2.2",
+ "fedora-1" => "redhat-6.2",
+ "fedora-2" => "redhat-6.2",
+ "fedora-3" => "redhat-6.2",
+ "fedora-4" => "redhat-6.2",
+ "fedora-5" => "redhat-6.2",
+ "rpath" => "redhat-6.2",
+ "vine-3.0" => "redhat-6.2",
+ "vine-3.1" => "redhat-6.2",
+ "ark" => "redhat-6.2",
+ "slackware-9.1.0" => "redhat-6.2",
+ "slackware-10.0.0" => "redhat-6.2",
+ "slackware-10.1.0" => "redhat-6.2",
+ "slackware-10.2.0" => "redhat-6.2",
+ "gentoo" => "debian-2.2",
+ "vlos-1.2" => "debian-2.2",
+ "freebsd-5" => "debian-2.2",
+ "freebsd-6" => "debian-2.2",
+ );
+
+ return $cmd_map{$dist_map{$gst_dist}};
+}
+
+
+# Run ping, taking what looks like the replying host addresses, return
+# colon-sepparated (:) string. To be used with gst_process_fork.
+sub gst_network_ping_broadcast_call
+{
+ my ($bcast) = @_;
+ my ($cmd, %hosts, $fd);
+
+ $cmd = &gst_network_get_broadcast_ping_cmd ($bcast);
+ $fd = &gst_file_run_pipe_read ($cmd);
+ return undef if $fd eq undef;
+ while (<$fd>)
+ {
+ if (/([0-9.]+):?[ \t]+icmp_seq/)
+ {
+ # If it already exists, it is the second count, and we can return then.
+ last if exists $hosts{$1};
+ $hosts{$1} = 1 ;
+ }
+ }
+ &gst_file_close ($fd);
+
+ return join (':', keys (%hosts));
+}
+
+
+# Return an array of IPs of the hosts in all the adjacent local networks.
+sub gst_network_find_hosts
+{
+ my ($iface, $ifaces, $dev, $hosts_str, @hosts, $proc, @procs);
+
+ $ifaces = &gst_network_interfaces_get_info ();
+
+ foreach $dev (keys %$ifaces)
+ {
+ $iface = $$ifaces{$dev};
+ if ($$iface{"active"} && exists $$iface{"bcast"})
+ {
+ push @procs, &gst_process_fork (\&gst_network_ping_broadcast_call, $$iface{"bcast"});
+ }
+ }
+
+ &gst_process_list_check_ready (3, \@procs);
+
+ foreach $proc (@procs)
+ {
+ if ($$proc{"ready"})
+ {
+ sysread ($$proc{"fd"}, $hosts_str, 4096);
+ push @hosts, split (':', $hosts_str);
+ }
+ }
+
+ return @hosts;
+}
+
+
+# like, &gst_network_lookup_address_block ("132.248.10.2") returns 'dns2.unam.mx'
+# but watch it: it will block until libc timeouts or a result is found. If
+# nothing found, returns the address.
+sub gst_network_lookup_address_block
+{
+ my ($addr) = @_;
+ my $name;
+
+ $name = (gethostbyaddr (&gst_network_ipv4_str2vec ($addr), AF_INET))[0];
+ return $addr if length ($name) == 0;
+ return $name;
+}
+
+
+# To be called from gst_process_fork by the child.
+sub gst_network_address_lookup_call
+{
+ my ($addr) = @_;
+
+ return &gst_network_lookup_address_block ($addr);
+}
+
+
+# Fork a lookup process for every passed address, return ref to
+# array with info on every proc.
+sub gst_network_lookup_address_start
+{
+ my (@addrs) = @_;
+ my ($addr, $proc, @procs);
+
+ # Fork a lookup for every address.
+ foreach $addr (@addrs)
+ {
+ $proc = &gst_process_fork (\&gst_network_address_lookup_call, $addr);
+ $$proc{"addr"} = $addr;
+ push @procs, $proc;
+ }
+
+ return \@procs;
+}
+
+# Take a ref to a list of forked lookup processes,
+# and collect the information from those ready.
+sub gst_network_lookup_address_collect
+{
+ my ($procs) = @_;
+ my ($name, @names, $proc);
+
+ # For every process, if the "ready" flag is on, read info.
+ # Else, populate with the given address. Then kill child and wait for it to die.
+ foreach $proc (@$procs)
+ {
+ if ($$proc{"ready"})
+ {
+ sysread ($$proc{"fd"}, $name, 4096);
+ push @names, $name;
+ }
+ else
+ {
+ push @names, $$proc{"addr"};
+ }
+ &gst_process_kill ($proc);
+ }
+
+ return @names;
+}
+
+
+# like, &gst_network_lookup_address (10, "132.248.10.2", "132.248.29.8") returns
+# 'dns2.unam.mx', 'sphinx.nuclecu.unam.mx' after 10 seconds, in the worst case.
+# If any of the given addresses is not resolved before timeout, the address will
+# be returned as its name. Timeout of 0 or undef blocks.
+# Timeout may be a decimal (0.5, half a second). You can split this process in
+# two, so you can collect the information at the last moment, giving more time for
+# the lookups to take place. Use the two functions above for this, as shown here.
+sub gst_network_lookup_address
+{
+ my ($timeout, @addrs) = @_;
+ my $procs;
+
+ $procs = &gst_network_lookup_address_start (@addrs);
+ &gst_process_list_check_ready ($timeout, $procs);
+ return &gst_network_lookup_address_collect ($procs);
+}
+
+
+# This code is not under the portable table style because it is supposed to
+# depend on wvdial.
+sub gst_network_dialing_get
+{
+ my %vars =
+ (
+ "Inherits" => "inherits",
+ "Modem" => "device",
+ "Baud" => "speed",
+ "Init1" => "init1",
+ "Init2" => "init2",
+ "Phone" => "phone",
+ "Username" => "login",
+ "Password" => "password",
+ "Dial Command" => "dialcmd",
+ "SetVolume" => "volume",
+ "Stupid mode" => "stupid",
+ "Auto Reconnect" => "persist",
+ "Force Address" => "address",
+ "Auto DNS" => "update_dns",
+ "Check Def Route" => "set_default_gw",
+ "GST Device" => "gst_dev",
+ "Dial Command" => "dial_command"
+ );
+ my %title2type =
+ (
+ "Dialer (.*)" => "dialer",
+ "Modem(.*)" => "modem"
+ );
+
+ my ($file) = @_;
+ my (%ret, @sections);
+ my ($i, $j, $name, $val);
+
+ &gst_report_enter ();
+ &gst_report ("network_dialing_get");
+
+ @sections = &gst_parse_ini_sections ($file);
+ foreach $i (@sections)
+ {
+ my %hash;
+
+ $hash{"type"} = "unknown";
+ foreach $j (keys %title2type)
+ {
+ if ($i =~ /$j/)
+ {
+ $hash{"name"} = $1;
+ $hash{"type"} = $title2type{$j};
+ }
+ }
+
+ $ret{$hash{"name"}} = \%hash;
+
+ foreach $j (keys %vars)
+ {
+ $val = &gst_parse_ini ($file, $i, $j);
+ $hash{$vars{$j}} = $val if ($val ne undef);
+ }
+
+ # we add the volume label, it's not a line in the wvdial config,
+ # it's a hayes command in the init2 string, it can be ATM0 or ATL[1-3]
+ if ($hash{"init2"} =~ /M0/)
+ {
+ $hash{"volume"} = 0;
+ }
+ elsif ($hash{"init2"} =~ /L[1-3]/)
+ {
+ $hash{"init2"} =~ /.*L([1-3]).*/;
+ $volume = ($1);
+ $hash{"volume"} = $volume;
+ }
+ else
+ {
+ $hash{"volume"} = 3;
+ }
+
+ # add the external line access number
+ if ($hash{"phone"} =~ /(^.*)[wW]/)
+ {
+ $hash{"external_line"} = $1;
+ $hash{"phone"} =~ s/^.*[wW]//;
+ }
+ }
+
+ &gst_report_leave ();
+ return \%ret;
+}
+
+# returns interface type depending on it's interface name
+# types_cache is a global var for caching interface types
+sub gst_network_get_interface_type
+{
+ my ($dev) = @_;
+ my (@wireless_ifaces, $wi, $type);
+
+ return $types_cache{$dev} if (exists $types_cache{$dev});
+
+ #check whether interface is wireless
+ $wireless_ifaces = &gst_network_get_wireless_ifaces ();
+ foreach $wi (@$wireless_ifaces)
+ {
+ if ($dev eq $wi)
+ {
+ $types_cache{$dev} = "wireless";
+ return $types_cache{$dev};
+ }
+ }
+
+ if ($dev =~ /^(ppp|tun)/)
+ {
+ # check whether the proper plugin exists
+ if (&gst_network_check_pppd_plugin ("capiplugin"))
+ {
+ $types_cache{$dev} = "isdn";
+ }
+ else
+ {
+ $types_cache{$dev} = "modem";
+ }
+ }
+ elsif ($dev =~ /^(eth|dc|ed|bfe|em|fxp|bge|de|xl|ixgb|txp|vx|lge|nge|pcn|re|rl|sf|sis|sk|ste|ti|tl|tx|vge|vr|wb|cs|ex|ep|fe|ie|lnc|sn|xe|le|an|awi|wi|ndis|wlaue|axe|cue|kue|rue|fwe|nve)[0-9]/)
+ {
+ $types_cache{$dev} = "ethernet";
+ }
+ elsif ($dev =~ /^irlan[0-9]/)
+ {
+ $types_cache{$dev} = "irlan";
+ }
+ elsif ($dev =~ /^plip[0-9]/)
+ {
+ $types_cache{$dev} = "plip";
+ }
+ elsif ($dev =~ /^lo[0-9]?/)
+ {
+ $types_cache{$dev} = "loopback";
+ }
+
+ return $types_cache{$dev};
+}
+
+sub gst_network_freebsd_interfaces_get_info
+{
+ my ($dev, %ifaces, $fd);
+
+ &gst_report_enter ();
+ &gst_report ("network_iface_active_get");
+
+ $fd = &gst_file_run_pipe_read ("ifconfig");
+ return {} if $fd eq undef;
+
+ while (<$fd>)
+ {
+ chomp;
+ if (/^([^ \t:]+):.*(<.*>)/)
+ {
+ $dev = $1;
+ $ifaces{$dev}{"dev"} = $dev;
+ $ifaces{$dev}{"enabled"} = 1 if ($2 =~ /[<,]UP[,>]/);
+ }
+
+ s/^[ \t]+//;
+ if ($dev)
+ {
+ $ifaces{$dev}{"hwaddr"} = $1 if /ether[ \t]+([^ \t]+)/i;
+ $ifaces{$dev}{"addr"} = $1 if /inet[ \t]+([^ \t]+)/i;
+ $ifaces{$dev}{"mask"} = $1 if /netmask[ \t]+([^ \t]+)/i;
+ $ifaces{$dev}{"bcast"} = $1 if /broadcast[ \t]+([^ \t]+)/i;
+ }
+ }
+
+ &gst_file_close ($fd);
+ &gst_report_leave ();
+ return \%ifaces;
+}
+
+sub gst_network_linux_interfaces_get_info
+{
+ my ($dev, %ifaces, $fd);
+
+ &gst_report_enter ();
+ &gst_report ("network_iface_active_get");
+
+ $fd = &gst_file_run_pipe_read ("ifconfig -a");
+ return {} if $fd eq undef;
+
+ while (<$fd>)
+ {
+ chomp;
+ if (/^([^ \t:]+)/)
+ {
+ $dev = $1;
+ $ifaces{$dev}{"enabled"} = 0;
+ $ifaces{$dev}{"dev"} = $dev;
+ }
+
+ s/^[ \t]+//;
+ if ($dev)
+ {
+ $ifaces{$dev}{"hwaddr"} = $1 if /HWaddr[ \t]+([^ \t]+)/i;
+ $ifaces{$dev}{"addr"} = $1 if /addr:([^ \t]+)/i;
+ $ifaces{$dev}{"mask"} = $1 if /mask:([^ \t]+)/i;
+ $ifaces{$dev}{"bcast"} = $1 if /bcast:([^ \t]+)/i;
+ $ifaces{$dev}{"enabled"} = 1 if /^UP[ \t]/i;
+ }
+ }
+
+ &gst_file_close ($fd);
+ &gst_report_leave ();
+ return \%ifaces;
+}
+
+sub gst_network_interfaces_get_info
+{
+ my (%ifaces);
+
+ $ifaces = &gst_network_linux_interfaces_get_info if ($$tool{"system"} eq "Linux");
+ $ifaces = &gst_network_freebsd_interfaces_get_info if ($$tool{"system"} eq "FreeBSD");
+
+ foreach $dev (keys %$ifaces)
+ {
+ #$$ifaces{$dev}{"enabled"} = 0 if $$ifaces{$dev}{"addr"} eq undef;
+ $$ifaces{$dev}{"type"} = &gst_network_get_interface_type ($dev);
+
+ #delete unknown ifaces
+ if ($$ifaces{$dev}{"type"} eq undef)
+ {
+ delete $$ifaces{$dev};
+ }
+ }
+
+ return $ifaces;
+}
+
+sub gst_network_active_interfaces_get
+{
+ my $fd;
+ my @ret = ();
+
+ &gst_report_enter ();
+ &gst_report ("network_iface_active_get");
+
+ $fd = &gst_file_run_pipe_read ("ifconfig");
+ return undef if $fd eq undef;
+
+ while (<$fd>)
+ {
+ chomp;
+ s/:? .*//;
+ next if /^$/;
+ push @ret, $_;
+ }
+
+ &gst_file_close ($fd);
+
+ &gst_report_leave ();
+ return @ret;
+}
+
+sub gst_network_freebsd5_active_interfaces_get
+{
+ my ($fd, @ret);
+
+ &gst_report_enter ();
+ &gst_report ("network_iface_active_get");
+
+ $fd = &gst_file_run_pipe_read ("ifconfig");
+ return undef if ($fd eq undef);
+
+ while (<$fd>)
+ {
+ chomp;
+ if (/^([\w\d]*):.*[<,]UP[,>]/)
+ {
+ push @ret, $1;
+ }
+ }
+
+ &gst_file_close ($fd);
+ &gst_report_leave ();
+
+ return @ret;
+}
+
+sub gst_network_suse70_active_interfaces_get
+{
+ my (@devs, $dev, @ret, $num);
+
+ @devs = &gst_network_active_interfaces_get ();
+
+ foreach $dev (@devs)
+ {
+ if ($dev ne "lo")
+ {
+ $num = &gst_network_suse70_parse_iface_num ("$gst_prefix/etc/rc.config", $dev);
+ push @ret, $num if $num != -1;
+ }
+ }
+
+ return @ret;
+}
+
+sub gst_network_interface_active
+{
+ my ($search_iface, $proc) = @_;
+ my @ifaces;
+
+ &gst_report_enter ();
+ &gst_report ("network_iface_is_active", $search_iface);
+
+ @ifaces = &$proc ();
+ while ($ifaces[0] ne "")
+ {
+ return 1 if (shift (@ifaces) eq $search_iface);
+ }
+
+ &gst_report_leave ();
+ return 0;
+}
+
+sub gst_network_interface_ensure_broadcast_and_network
+{
+ my ($iface) = @_;
+
+ if (exists $$iface{"netmask"} &&
+ exists $$iface{"address"})
+ {
+ if (! exists $$iface{"broadcast"})
+ {
+ $$iface{"broadcast"} = &gst_network_ipv4_calc_bcast ($$iface{"address"}, $$iface{"netmask"});
+ }
+
+ if (! exists $$iface{"network"})
+ {
+ $$iface{"network"} = &gst_network_ipv4_calc_subnet ($$iface{"address"}, $$iface{"netmask"});
+ }
+ }
+}
+
+sub gst_network_sysconfig_dir_ifaces_get_existing
+{
+ my ($dir) = @_;
+ my (@ret, $i, $name);
+ local *IFACE_DIR;
+
+ if (opendir IFACE_DIR, "$gst_prefix/$dir")
+ {
+ foreach $i (readdir (IFACE_DIR))
+ {
+ push @ret, $1 if ($i =~ /^ifcfg-(.+)$/);
+ }
+
+ closedir (IFACE_DIR);
+ }
+
+ return \@ret;
+}
+
+sub gst_network_sysconfig_rh62_ifaces_get_existing
+{
+ return @{&gst_network_sysconfig_dir_ifaces_get_existing ("/etc/sysconfig/network-scripts")};
+}
+
+sub gst_network_sysconfig_rh72_ifaces_get_existing
+{
+ my ($ret);
+
+ # This syncs /etc/sysconfig/network-scripts and /etc/sysconfig/networking
+ &gst_file_run ("redhat-config-network-cmd");
+
+ $ret = &gst_network_sysconfig_dir_ifaces_get_existing
+ ("/etc/sysconfig/networking/profiles/default");
+
+ &gst_arr_merge ($ret,
+ &gst_network_sysconfig_dir_ifaces_get_existing
+ ("/etc/sysconfig/networking/devices"));
+
+ return @$ret;
+}
+
+sub gst_network_debian_ifaces_get_existing
+{
+ my (@ret, @stanzas, $stanza);
+
+ @stanzas = &gst_parse_interfaces_stanzas ("$gst_prefix/etc/network/interfaces", "iface");
+
+ foreach $stanza (@stanzas)
+ {
+ if ($$stanza[1] eq "inet")
+ {
+ push @ret, $$stanza[0];
+ }
+ }
+
+ return @ret;
+}
+
+sub gst_network_suse70_ifaces_get_existing
+{
+ my $file = "$gst_prefix/etc/rc.config";
+ my ($i, $dev, @ret, $fd);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ return @ret if !$fd;
+
+ while ($i = <$fd>)
+ {
+ if ($i =~ /^[ \t]*NETDEV_([0-9]+)=/)
+ {
+ push @ret, $1 if &gst_parse_sh ($file, "NETDEV_$1") ne "";
+ }
+ }
+
+ &gst_file_close ($fd);
+ return @ret;
+}
+
+sub gst_network_suse90_ifaces_get_existing
+{
+ return @{&gst_network_sysconfig_dir_ifaces_get_existing ("/etc/sysconfig/network")};
+}
+
+sub gst_network_sysconfig_pld10_ifaces_get_existing
+{
+ return @{&gst_network_sysconfig_dir_ifaces_get_existing ("/etc/sysconfig/interfaces")};
+}
+
+sub gst_network_slackware91_ifaces_get_existing
+{
+ my $file = "/etc/rc.d/rc.inet1.conf";
+ my $pppscript = "/etc/ppp/pppscript";
+ my ($fd, $i, @ret);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ return @ret if !$fd;
+
+ while ($i = <$fd>)
+ {
+ if ($i =~ /^[ \t]*(IPADDR|USE_DHCP)\[([0-9]+)\][ \t]*=[ \t]*"(.*)"/)
+ {
+ push @ret, "eth$2" if ($3 ne "");
+ }
+ }
+
+ &gst_file_close ($fd);
+
+ if (&gst_file_exists ($pppscript))
+ {
+ push @ret, "ppp0";
+ }
+
+ return @ret;
+}
+
+sub gst_network_gentoo_ifaces_get_existing
+{
+ my $file = "/etc/conf.d/net";
+ my ($fd, $i, @ret, $ppp);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ return @ret if !$fd;
+
+ while ($i = <$fd>)
+ {
+ if ($i =~ /^config_([a-zA-Z0-9]*)[ \t]*=/)
+ {
+ push @ret, $1;
+ }
+ }
+
+ #now the PPP ifaces
+ foreach $ppp (</etc/conf.d/net.*>)
+ {
+ $ppp =~ s#^/etc/conf.d/net\.##;
+ push @ret, $ppp if ($ppp =~ /^ppp[0-9]$/);
+ }
+
+ return @ret;
+}
+
+sub gst_network_freebsd_ifaces_get_existing
+{
+ my $file = "/etc/rc.conf";
+ my ($fd, $i, @ret);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ return @ret if !$fd;
+
+ while ($i = <$fd>)
+ {
+ if ($i =~ /^ifconfig_(.*)[ \t]*=/)
+ {
+ push @ret, $1;
+ }
+ }
+
+ return @ret;
+}
+
+sub gst_network_suse70_parse_iface_num
+{
+ my ($file, $dev) = @_;
+ my ($i, $ret);
+
+ foreach $i (&gst_network_suse70_ifaces_get_existing ())
+ {
+ $ret = &gst_parse_sh ($file, "NETDEV_$i");
+ return $i if $ret eq $dev;
+ }
+
+ &gst_debug_print_string ("\n\nWarning: gst_network_suse70_parse_iface_num: num for $dev not found.\n\n");
+ return -1;
+}
+
+sub gst_network_suse70_parse_iface_auto
+{
+ my ($file, $iface, $key) = @_;
+ my ($val, $i);
+
+ $val = &gst_parse_sh_split ($file, $key, "[ \t]+");
+
+ foreach $i (@$val)
+ {
+ return 1 if $i eq "_$iface";
+ }
+
+ return 0;
+}
+
+sub gst_network_suse70_replace_iface_auto
+{
+ my ($file, $iface, $key, $value) = @_;
+ my ($val, $i, $found, @ret);
+
+ $val = &gst_parse_sh_split ($file, $key, "[ \t]+");
+
+ foreach $i (@$val)
+ {
+ $found = 1 if $i eq "_$iface";
+ push @ret, $i unless ($i eq "_$iface" && !$value);
+ }
+
+ return 0 if ($found == $value);
+ push @ret, "_$iface" if (!$found && $value);
+
+ return &gst_replace_sh ($file, $key, join (" ", @ret));
+}
+
+sub gst_network_suse70_parse_iface_sh
+{
+ my ($file, $iface, $key) = @_;
+ my ($val, $num);
+
+ return &gst_parse_sh ($file, "${key}_$iface");
+}
+
+sub gst_network_suse70_replace_iface_sh
+{
+ my ($file, $iface, $key, $value) = @_;
+ my ($val, $num);
+
+ return &gst_replace_sh ($file, "${key}_$iface", $value);
+}
+
+sub gst_network_suse70_get_ifconfig_arg
+{
+ my ($file, $iface, $key) = @_;
+ my ($val);
+
+ $val = &gst_network_suse70_parse_iface_sh ($file, $iface, "IFCONFIG");
+ $val =~ /[ \t]+$key[ \t]+([^ \t]+)/;
+ return $1;
+}
+
+sub gst_network_suse70_set_ifconfig_arg
+{
+ my ($file, $iface, $key, $value) = @_;
+ my ($val);
+
+ $val = &gst_network_suse70_parse_iface_sh ($file, $iface, "IFCONFIG");
+
+ return 0 if $val =~ /^dhcpclient$/ || $val =~ /^bootp$/;
+
+ if (! ($val =~ s/([ \t]+$key[ \t]+)[^ \t]+/$1$value/))
+ {
+ $val =~ s/[ \t]+up$//;
+ $val .= " " if $val =~ /[^ \t]$/;
+ $val .= "$key $value up";
+ }
+
+ return &gst_network_suse70_replace_iface_sh ($file, $iface, "IFCONFIG", $val);
+}
+
+sub gst_network_suse70_set_ifconfig_ip
+{
+ my ($file, $iface, $value) = @_;
+
+ $val = &gst_network_suse70_parse_iface_sh ($file, $iface, "IFCONFIG");
+
+ return 0 if $val =~ /^dhcpclient$/ || $val =~ /^bootp$/;
+
+ if (! ($val =~ s/^[0-9\.]+([ \t])/$value$1/))
+ {
+ $val = "$value $val";
+ $val =~ s/[ \t]+/ /;
+ }
+
+ return &gst_network_suse70_replace_iface_sh ($file, $iface, "IFCONFIG", $val);
+}
+
+sub gst_network_get_new_dialing_dev
+{
+ my ($dial_hash, $type) = @_;
+ my ($dial, $dev, $maxdev);
+
+ $maxdev = -1;
+ foreach $dial (keys %$dial_hash)
+ {
+ $dev = $ {$$dial_hash{$dial}}{"gst_dev"};
+ if ($dev ne "")
+ {
+ if ($dev =~ s/^$type//)
+ {
+ $maxdev = $dev if $dev > $maxdev;
+ }
+ }
+ }
+
+ $maxdev ++;
+ return "$type$maxdev";
+}
+
+sub gst_network_dial2iface
+{
+ my ($dial_hash, $name) = @_;
+ my ($dial, %iface, $i);
+
+ my %map = ("address" => "address",
+ "update_dns" => "update_dns",
+ "login" => "login",
+ "password" => "password",
+ "serial_port" => "device",
+ "serial_speed" => "speed",
+ "set_default_gw" => "set_default_gw",
+ "persist" => "persist",
+ "phone_number" => "phone",
+ "dev" => "gst_dev"
+ );
+
+ $dial = $$dial_hash{$name};
+ if ($$dial{"gst_dev"} eq "")
+ {
+ $$dial{"gst_dev"} = "ppp0";
+ # = &gst_network_get_new_dialing_dev ($dial_hash, "ppp");
+ }
+ else
+ {
+ $iface{"enabled"} = &gst_network_interface_active ($$dial{"gst_dev"},
+ \&gst_network_active_interfaces_get)? 1: 0;
+ }
+
+ foreach $i (keys %map)
+ {
+ $iface{$i} = $$dial{$map{$i}} if exists $$dial{$map{$i}};
+ }
+
+ $iface{"file"} = $iface{"name"} = $iface{"section"} = $name;
+ $iface{"update_dns"} = 1 if ($iface{"update_dns"} eq "");
+ $iface{"set_default_gw"} = 1 if ($iface{"set_default_gw"} eq "");
+
+ return \%iface;
+}
+
+sub gst_network_iface2dial
+{
+ my ($dial_hash, $iface) = @_;
+ my ($dial, $i);
+
+ my %map = ("address" => "address",
+ "update_dns" => "update_dns",
+ "device" => "serial_port",
+ "speed" => "serial_speed",
+ "set_default_gw" => "set_default_gw",
+ "persist" => "persist",
+ "gst_dev" => "dev"
+ );
+
+ $dial = $$dial_hash{$$iface{"name"}};
+
+ foreach $i (keys %map)
+ {
+ $$dial{$i} = $$iface{$map{$i}} if exists $$iface{$map{$i}};
+ }
+
+ $$dial{"type"} = "dialer";
+}
+
+sub gst_network_suse70_get_ppp
+{
+ my ($dial, $iface) = @_;
+ my ($d);
+
+ foreach $d (keys %$dial)
+ {
+ $$iface{$d} = &gst_network_dial2iface ($dial, $d);
+ }
+
+ return $iface;
+}
+
+sub gst_network_suse70_set_ppp
+{
+ my ($wvfile, $dial, $iface) = @_;
+ my ($d, $i, @ppp_devs, $section);
+
+ foreach $d (keys %$iface)
+ {
+ $i = $$iface{$d};
+ if ($$i{"dev"} =~ /^ppp/)
+ {
+ my ($tmp, $wv, $name);
+
+ push @ppp_devs, $i;
+
+ # This takes care of connection name changes.
+ $wv = $$i{"section"};
+ $name = $$i{"name"};
+
+ if ($wv ne $name)
+ {
+ $tmp = $$dial{$wv};
+ delete $$dial{$wv};
+ $$tmp{"name"} = $name;
+ $$dial{$name} = $tmp;
+ }
+
+ # Then merges interface with dialing.
+ &gst_network_iface2dial ($dial, $i);
+ }
+ }
+
+ # Delete any wvdial sections that are no longer present as ifaces.
+ OUTER: foreach $d (keys %$dial)
+ {
+ foreach $i (@ppp_devs)
+ {
+ next OUTER if $$i{"name"} eq $ {$$dial{$d}}{"name"};
+ }
+
+ # Don't delete the defaults: that's not very polite.
+ delete $$dial{$d} unless $ {$$dial{$d}}{"name"} eq "Defaults";
+ }
+
+ return 0;
+}
+
+sub gst_network_suse70_ppp_iface_activate
+{
+ my ($name, $enabled);
+ my ($wvdial_dod, $tool_ifconfig, @paths);
+
+ @paths = &gst_service_sysv_get_paths ();
+ $wvdial_dod = $paths[1] . "/wvdial.dod";
+ $tool_ifconfig = &gst_file_locate_tool ("ifconfig");
+
+ if ($enabled)
+ {
+ &gst_debug_print_string ("\n\nifup ppp iface $name\n\n");
+ return -1 if &gst_file_run_bg ("$wvdial_dod start \"$name\"");
+ }
+ else
+ {
+ # Hmm... you'd better not have more than one ppp connection active:
+ # this is the only SuSE way of doing it.
+ &gst_debug_print_string ("\n\nifdown ppp iface $name\n\n");
+ return -1 if &gst_file_run ("$wvdial_dod stop");
+ }
+
+ return 0;
+}
+
+sub gst_network_suse70_activate_ppp
+{
+ my ($iface) = @_;
+ my ($d, $i);
+
+ foreach $d (keys %$iface)
+ {
+ $i = $$iface{$d};
+ if ($$i{"dev"} =~ /^ppp/ && (! $$i{"enabled"}))
+ {
+ &gst_network_suse70_ppp_iface_activate ($$i{"name"}, 0);
+ # deleted, so interfaces_set doesn't handle them.
+ delete $$iface{$d};
+ }
+ }
+
+ foreach $d (keys %$iface)
+ {
+ $i = $$iface{$d};
+ if ($$i{"dev"} =~ /^ppp/ && $$i{"enabled"})
+ {
+ &gst_network_suse70_ppp_iface_activate ($$i{"name"}, 1);
+ delete $$iface{$d};
+ }
+ }
+
+ return 0;
+}
+
+sub gst_network_slackware91_create_pppgo
+{
+ my ($pppgo) = "/usr/sbin/ppp-go";
+ my ($contents, $pppd, $chat);
+ local *FILE;
+
+ if (!&gst_file_exists ($pppgo))
+ {
+ $pppd = &gst_file_locate_tool ("pppd");
+ $chat = &gst_file_locate_tool ("chat");
+
+ # create a simple ppp-go from scratch
+ # this script is based on the one that's created by pppsetup
+ $contents = "killall -INT pppd 2>/dev/null \n";
+ $contents .= "rm -f /var/lock/LCK* /var/run/ppp*.pid \n";
+ $contents .= "( $pppd connect \"$chat -v -f /etc/ppp/pppscript\") || exit 1 \n";
+ $contents .= "exit 0 \n";
+
+ &gst_file_buffer_save ($contents, $pppgo);
+ chmod 0777, "$gst_prefix/$pppgo";
+ }
+}
+
+sub gst_network_get_modem_volume
+{
+ my ($file) = @_;
+ my ($volume);
+
+ $volume = &gst_parse_chat ($file, "AT.*(M0|L[1-3])");
+
+ return 3 if ($volume eq undef);
+
+ $volume =~ s/^[ml]//i;
+ return $volume;
+}
+
+sub gst_network_set_modem_volume_string
+{
+ my ($file, $key, $volume) = @_;
+ my ($vol);
+
+ if ($volume == 0) { $vol = "ATM0" }
+ elsif ($volume == 1) { $vol = "ATL1" }
+ elsif ($volume == 2) { $vol = "ATL2" }
+ else { $vol = "ATL3" }
+
+ return &gst_replace_sh ($file, $key, $vol);
+}
+
+sub gst_network_set_modem_volume
+{
+ my ($file, $volume) = @_;
+ my $line;
+
+ $line = &gst_parse_chat ($file, "AT([^DZ][a-z0-9&]+)");
+ $line =~ s/(M0|L[1-3])//g;
+
+ if ($volume == 0) { $line .= "M0"; }
+ elsif ($volume == 1) { $line .= "L1"; }
+ elsif ($volume == 2) { $line .= "L2"; }
+ else { $line .= "L3"; }
+
+ return &gst_replace_chat ($file, "AT([^DZ][a-z0-9&]+)", $line);
+}
+
+sub gst_network_create_pppscript
+{
+ my ($pppscript) = @_;
+ my ($contents);
+
+ if (!&gst_file_exists ($pppscript))
+ {
+ # create a template file from scratch
+ $contents = 'TIMEOUT 60' . "\n";
+ $contents .= 'ABORT ERROR' . "\n";
+ $contents .= 'ABORT BUSY' . "\n";
+ $contents .= 'ABORT VOICE' . "\n";
+ $contents .= 'ABORT "NO CARRIER"' . "\n";
+ $contents .= 'ABORT "NO DIALTONE"' . "\n";
+ $contents .= 'ABORT "NO DIAL TONE"' . "\n";
+ $contents .= 'ABORT "NO ANSWER"' . "\n";
+ $contents .= '"" "ATZ"' . "\n";
+ $contents .= '"" "AT&FH0"' . "\n";
+ $contents .= 'OK-AT-OK "ATDT000000000"' . "\n";
+ $contents .= 'TIMEOUT 75' . "\n";
+ $contents .= 'CONNECT' . "\n";
+
+ &gst_file_buffer_save ($contents, $pppscript);
+ }
+}
+
+sub gst_network_create_isdn_options
+{
+ my ($file) = @_;
+
+ if (!&gst_file_exists ($file))
+ {
+ &gst_file_copy_from_stock ("general_isdn_ppp_options", $file);
+ }
+}
+
+sub gst_network_check_pppd_plugin
+{
+ my ($plugin) = @_;
+ my ($version, $output);
+
+ $version = &gst_file_run_backtick ("pppd --version", 1);
+ $version =~ s/.*version[ \t]+//;
+ chomp $version;
+
+ return 0 if !version;
+ return &gst_file_exists ("/usr/lib/pppd/$version/$plugin.so");
+}
+
+sub gst_network_gentoo_parse_gateway
+{
+ my ($file, $iface) = @_;
+ my ($str);
+
+ $str = &gst_parse_confd_net ($file, "routes_$iface");
+
+ if ($str =~ /default[ \t]+(via|gw)[ \t]+([0-9\.\:]*)/)
+ {
+ return $2;
+ }
+}
+
+sub gst_network_interfaces_get
+{
+ my (%dist_attrib, %config_hash, %hash, %fn);
+ my (@config_ifaces, $iface, $dev);
+ my ($dist, $value, $file, $proc);
+ my ($i, $j);
+ my ($modem_settings);
+
+ $hash = &gst_network_interfaces_get_info ();
+ %dist_attrib = &gst_network_get_interface_parse_table ();
+ %fn = %{$dist_attrib{"fn"}};
+ $proc = $dist_attrib{"ifaces_get"};
+ @ifaces = &$proc ();
+
+ # clear unneeded hash elements
+ foreach $i (keys %$hash)
+ {
+ delete $$hash{$i}{"addr"};
+ delete $$hash{$i}{"bcast"};
+ delete $$hash{$i}{"mask"};
+ }
+
+ foreach $i (@ifaces)
+ {
+ foreach $j (keys (%fn))
+ {
+ $ {$dist_attrib{"fn"}}{$j} = &gst_parse_expand ($fn{$j}, "iface", $i);
+ }
+
+ $iface = &gst_parse_from_table ($dist_attrib{"fn"},
+ $dist_attrib{"table"});
+ &gst_network_interface_ensure_broadcast_and_network ($iface);
+ $$iface{"file"} = $i if ($$iface{"file"} eq undef);
+
+ $dev = $$iface{"dev"};
+ delete $$iface{"dev"};
+
+ if (exists $$hash{$dev})
+ {
+ $$hash{$dev}{"configuration"} = $iface;
+ }
+ elsif (($dev eq "ppp0") || ($dev eq "tun0"))
+ {
+ $modem_settings = $iface;
+ }
+ }
+
+ # only show PPP and ISDN devices if pppd exists
+ # and they aren't configured yet
+ $dev = "ppp0" if ($$tool{"system"} eq "Linux");
+ $dev = "tun0" if ($$tool{"system"} eq "FreeBSD");
+
+ if (!exists $$hash{$dev} && &gst_file_locate_tool ("pppd"))
+ {
+ $$hash{$dev}{"dev"} = $dev;
+ $$hash{$dev}{"enabled"} = 0;
+ $$hash{$dev}{"type"} = &gst_network_get_interface_type ($dev);
+ $$hash{$dev}{"configuration"} = $modem_settings if ($modem_settings);
+ }
+
+ return \%$hash;
+}
+
+sub gst_network_conf_get
+{
+ my %dist_attrib;
+ my $hash;
+
+ %dist_attrib = &gst_network_get_parse_table ();
+
+ $hash = &gst_parse_from_table ($dist_attrib{"fn"},
+ $dist_attrib{"table"});
+ return $hash;
+}
+
+sub gst_network_rh_get_smb_desc
+{
+ my ($file, $section, $var, $hostname) = @_;
+ my $val;
+
+ $val = &gst_parse_ini ($file, $section, $var);
+ if (($val =~ /^Samba Server/) && ($hostname ne undef))
+ {
+ return $hostname;
+ }
+
+ return $val;
+}
+
+sub gst_network_rh62_get_file
+{
+ my ($iface) = @_;
+ my ($pre, $i, $dev);
+
+ $dev = $$iface{"dev"};
+ $pre = "$gst_prefix/etc/sysconfig/network-scripts/ifcfg-";
+
+ return $dev if ! -e "$pre$dev";
+
+ $dev =~ s/[0-9]*$//;
+
+ $i = 0;
+ $i ++ while (-e "$pre$dev$i");
+
+ return "$dev$i";
+}
+
+sub gst_network_rh72_get_file
+{
+ my ($iface) = @_;
+ my ($pre, $i, $dev);
+
+ $dev = $$iface{"dev"};
+ $pre = "$gst_prefix/etc/sysconfig/networking/devices/ifcfg-";
+
+ return $dev if ! -e "$pre$dev";
+
+ $i = 0;
+ $i ++ while (-e "$pre$dev.$i");
+
+ return "$dev.$i";
+}
+
+sub gst_network_deb22_get_file
+{
+ my ($iface) = @_;
+
+ return $$iface{"dev"};
+}
+
+sub gst_network_suse70_get_file
+{
+ my ($i, $file);
+
+ $file = "$gst_prefix/etc/rc.config";
+
+ $i = 0;
+ $i ++ while (&gst_parse_sh ($file, "NETDEV_$i") ne "");
+
+ return $i;
+}
+
+sub gst_network_pld10_get_file
+{
+ my ($iface) = @_;
+ my ($pre, $i, $dev);
+
+ $dev = $$iface{"dev"};
+ $pre = "$gst_prefix/etc/sysconfig/interfaces/ifcfg-";
+
+ return $dev if ! -e "$pre$dev";
+
+ $dev =~ s/[0-9]*$//;
+
+ $i = 0;
+ $i ++ while (-e "$pre$dev$i");
+
+ return "$dev$i";
+}
+
+sub gst_network_get_file
+{
+ my ($iface) = @_;
+ my $proc;
+
+ my %dist_map =
+ (
+ "redhat-6.0" => \&gst_network_rh62_get_file,
+ "redhat-6.1" => \&gst_network_rh62_get_file,
+ "redhat-6.2" => \&gst_network_rh62_get_file,
+ "redhat-7.0" => \&gst_network_rh62_get_file,
+ "redhat-7.1" => \&gst_network_rh62_get_file,
+ "redhat-7.2" => \&gst_network_rh72_get_file,
+ "redhat-8.0" => \&gst_network_rh72_get_file,
+ "redhat-9" => \&gst_network_rh72_get_file,
+ "openna-1.0" => \&gst_network_rh62_get_file,
+ "mandrake-7.2" => \&gst_network_rh62_get_file,
+ "mandrake-7.1" => \&gst_network_rh62_get_file,
+ "mandrake-9.0" => \&gst_network_rh62_get_file,
+ "mandrake-9.1" => \&gst_network_rh62_get_file,
+ "mandrake-9.2" => \&gst_network_rh62_get_file,
+ "mandrake-10.0" => \&gst_network_rh62_get_file,
+ "mandrake-10.1" => \&gst_network_rh62_get_file,
+ "mandrake-10.2" => \&gst_network_rh62_get_file,
+ "mandriva-2006.0" => \&gst_network_rh62_get_file,
+ "mandriva-2006.1" => \&gst_network_rh62_get_file,
+ "mandriva-2007.0" => \&gst_network_rh62_get_file,
+ "mandriva-2007.1" => \&gst_network_rh62_get_file,
+ "yoper-2.2" => \&gst_network_rh62_get_file,
+ "blackpanther-4.0" => \&gst_network_rh62_get_file,
+ "conectiva-9" => \&gst_network_rh62_get_file,
+ "conectiva-10" => \&gst_network_rh62_get_file,
+ "debian-2.2" => \&gst_network_deb22_get_file,
+ "debian-3.0" => \&gst_network_deb22_get_file,
+ "debian-3.1" => \&gst_network_deb22_get_file,
+ "debian-4.0" => \&gst_network_deb22_get_file,
+ "debian-5.0" => \&gst_network_deb22_get_file,
+ "debian-testing" => \&gst_network_deb22_get_file,
+ "ubuntu-5.04" => \&gst_network_deb22_get_file,
+ "ubuntu-5.10" => \&gst_network_deb22_get_file,
+ "ubuntu-6.06" => \&gst_network_deb22_get_file,
+ "ubuntu-6.10" => \&gst_network_deb22_get_file,
+ "ubuntu-7.04" => \&gst_network_deb22_get_file,
+ "ubuntu-7.10" => \&gst_network_deb22_get_file,
+ "ubuntu-8.04" => \&gst_network_deb22_get_file,
+ "suse-7.0" => \&gst_network_suse70_get_file,
+ "suse-9.0" => \&gst_network_deb22_get_file,
+ "suse-9.1" => \&gst_network_deb22_get_file,
+ "turbolinux-7.0" => \&gst_network_rh62_get_file,
+ "pld-1.0" => \&gst_network_pld10_get_file,
+ "pld-1.1" => \&gst_network_pld10_get_file,
+ "pld-1.99" => \&gst_network_pld10_get_file,
+ "fedora-1" => \&gst_network_rh72_get_file,
+ "fedora-2" => \&gst_network_rh72_get_file,
+ "fedora-3" => \&gst_network_rh72_get_file,
+ "fedora-4" => \&gst_network_rh72_get_file,
+ "fedora-5" => \&gst_network_rh72_get_file,
+ "rpath" => \&gst_network_rh72_get_file,
+ "vine-3.0" => \&gst_network_rh62_get_file,
+ "vine-3.1" => \&gst_network_rh62_get_file,
+ "ark" => \&gst_network_rh62_get_file,
+ "slackware-9.1.0" => \&gst_network_deb22_get_file,
+ "slackware-10.0.0" => \&gst_network_deb22_get_file,
+ "slackware-10.1.0" => \&gst_network_deb22_get_file,
+ "slackware-10.2.0" => \&gst_network_deb22_get_file,
+ "gentoo" => \&gst_network_deb22_get_file,
+ "freebsd-5" => \&gst_network_deb22_get_file,
+ "freebsd-6" => \&gst_network_deb22_get_file,
+ );
+
+ $proc = $dist_map{$gst_dist};
+
+ return &$proc ($iface) if $proc;
+
+ # FIXME: should make us bail.
+ &gst_debug_print_string ("\n\nWarning: No network_get_file proc for dist $gst_dist.\n\n");
+ return undef;
+}
+
+sub gst_network_get_gateway_data
+{
+ my ($fd, $gateway, $dev);
+
+ $fd = &gst_file_run_pipe_read ("route -n");
+ while (<$fd>)
+ {
+ if (/^0\.0\.0\.0[\t ]+([^\t ]+).*[ \t]([a-zA-Z0-9]*)/)
+ {
+ $gateway = $1;
+ $dev = $2;
+ last;
+ }
+ }
+
+ &gst_file_close ($fd);
+ return ($gateway, $dev);
+}
+
+sub gst_network_get_default_gatewaydev
+{
+ my ($gateway, $dev) = &gst_network_get_gateway_data ();
+
+ return $dev;
+}
+
+sub gst_network_get_default_gateway
+{
+ my ($gateway, $dev) = &gst_network_get_gateway_data ();
+
+ return $gateway;
+}
+
+sub gst_network_route_set_default_gw
+{
+ my ($gatewaydev, $gateway) = @_;
+ my ($tool_route, $curr_gateway, $curr_gatewaydev, $fd);
+
+ # Just in case. This means that no static gateway is needed.
+ return if $gateway eq "";
+
+ $fd = &gst_file_run_pipe_read ("route -n");
+ while (<$fd>)
+ {
+ if (/^0\.0\.0\.0[ \t]+([0-9.]+) /)
+ {
+ $curr_gateway = $1;
+ if ($gatewaydev ne "")
+ {
+ /([a-z0-9]+)$/;
+ $curr_gatewaydev = $1;
+ }
+
+ last;
+ }
+ }
+ &gst_file_close ($fd);
+
+ if (($curr_gateway ne $gateway) ||
+ ($curr_gatewaydev ne $gatewaydev))
+ {
+ &gst_file_run ("route del default gw $curr_gateway");
+ &gst_file_run ("route add default gw $gateway $gatewaydev");
+ }
+}
+
+sub gst_network_run_hostname
+{
+ my ($hostname) = @_;
+
+ &gst_report_enter ();
+ &gst_report ("network_hostname_set", $hostname);
+ &gst_file_run ("hostname $hostname");
+ &gst_report_leave ();
+}
+
+sub gst_network_dialing_get_section_name
+{
+ my ($dial) = @_;
+
+ my %type2title =
+ (
+ "dialer" => "Dialer ",
+ "modem" => "Modem ",
+ "unknown" => ""
+ );
+
+ return $type2title{$$dial{"type"}} . $$dial{"name"};
+}
+
+sub gst_network_dialing_set
+{
+ my ($file, $old_hash, $values_hash) = @_;
+ my %vars =
+ (
+ "inherits" => "Inherits",
+ "device" => "Modem",
+ "speed" => "Baud",
+ "init1" => "Init1",
+ "init2" => "Init2",
+ "phone" => "Phone",
+ "login" => "Username",
+ "password" => "Password",
+ "dialcmd" => "Dial Command",
+ "setvol" => "SetVolume",
+ "stupid" => "Stupid mode",
+ "persist" => "Auto Reconnect",
+ "address" => "Force Address",
+ "update_dns" => "Auto DNS",
+ "set_default_gw" => "Check Def Route",
+ "gst_dev" => "GST Device",
+ "dial_command" => "Dial Command"
+ );
+
+ my (%hash, $section);
+ my $ret;
+ my ($i, $j);
+
+ &gst_report_enter ();
+ &gst_report ("network_dialing_set");
+ &gst_file_run ("wvdialconf $gst_prefix/$file") if (!-e "$gst_prefix/$file");
+
+ # Remove those that are in old, but not in values.
+ $old_hash = $$old_hash{"dialing"};
+ OUTER: foreach $i (keys %$old_hash)
+ {
+ foreach $j (keys %$values_hash)
+ {
+ next OUTER if ($j eq $i) && ($ {$$values_hash{$j}}{"type"} eq $ {$$old_hash{$i}}{"type"});
+ }
+
+ $section = gst_network_dialing_get_section_name ($$old_hash{$i});
+ $ret = -1 if &gst_replace_remove_ini_section ($file, $section);
+ }
+
+ # Now save the current stuff.
+ foreach $i (keys %$values_hash)
+ {
+ %hash = %{$$values_hash{$i}};
+
+ $section = gst_network_dialing_get_section_name (\%hash);
+ delete $hash{"type"};
+ delete $hash{"name"};
+
+ # if init1 doesnt exist add one with ATZ
+ if (!$hash{"init1"})
+ {
+ $hash{"init1"} = "ATZ";
+ }
+
+ # add the volume settings to init2
+ if ($hash{"init2"} !~ /^(AT)/)
+ {
+ $hash{"init2"} = "AT";
+ }
+ $hash {"init2"} =~ s/L[1-3]//;
+ $hash {"init2"} =~ s/M[0-2]//;
+ if ($hash{"volume"} == 0)
+ {
+ $hash{"init2"} .= "M0";
+ }
+ else
+ {
+ $volume = $hash{"volume"};
+ $hash {"init2"} .= "L$volume";
+ }
+ delete $hash {"volume"};
+
+ # join again the "external_line" and "phone" tags
+ if ($hash{"external_line"} ne undef)
+ {
+ $hash{"phone"} = $hash{"external_line"} . "W" . $hash{"phone"};
+ delete $hash{"external_line"};
+ }
+
+ foreach $j (keys %hash)
+ {
+ $ret = -1 if &gst_replace_ini ($file, $section, $vars{$j}, $hash{$j});
+ }
+ }
+
+ &gst_report_leave ();
+
+ chmod (0600, $file) if !$ret;
+
+ return $ret;
+}
+
+# This works for all systems that have ifup/ifdown scripts.
+sub gst_network_rh62_interface_activate_by_dev
+{
+ my ($dev, $enabled) = @_;
+
+ &gst_report_enter ();
+
+ if ($enabled)
+ {
+ &gst_report ("network_iface_activate", $dev);
+ return -1 if &gst_file_run ("ifup $dev");
+ }
+ else
+ {
+ &gst_report ("network_iface_deactivate", $dev);
+ return -1 if &gst_file_run ("ifdown $dev");
+ }
+
+ &gst_report_leave ();
+
+ return 0;
+}
+
+sub gst_network_rh62_interface_activate
+{
+ my ($hash, $old_hash, $enabled, $force) = @_;
+ my $dev;
+
+ if ($force || &gst_network_interface_changed ($hash, $old_hash))
+ {
+ if (exists $$hash{"configuration"}{"file"})
+ {
+ $dev = $$hash{"configuration"}{"file"};
+ }
+ else
+ {
+ $dev = $$hash{"dev"};
+ }
+
+ &gst_network_rh62_interface_activate_by_dev ($dev, $enabled);
+ }
+}
+
+sub gst_network_suse9_interface_activate
+{
+ my ($hash, $old_hash, $enabled, $force) = @_;
+ my ($iface, $dev);
+
+ if ($force || &gst_network_interface_changed ($hash, $old_hash))
+ {
+ if (exists $$hash{"configuration"}{"file"})
+ {
+ $iface = $$hash{"configuration"}{"file"};
+ $dev = &gst_network_suse9_get_dev_name ($iface);
+ }
+ else
+ {
+ $dev = $$hash{"dev"};
+ }
+
+ &gst_network_rh62_interface_activate_by_dev ($dev, $enabled);
+ }
+}
+
+sub gst_network_suse70_interface_activate_by_dev
+{
+ my ($dev, $enabled) = @_;
+ my ($network, @paths);
+
+ @paths = &gst_service_sysv_get_paths ();
+ $network = $paths[1] . "/network";
+
+ &gst_report_enter ();
+
+ if ($enabled)
+ {
+ &gst_report ("network_iface_deactivate", $hash{"dev"});
+ return -1 if &gst_file_run_bg ("$network start $dev");
+ }
+ else
+ {
+ &gst_report ("network_iface_activate", $hash{"dev"});
+ return -1 if &gst_file_run ("$network stop $dev");
+ }
+
+ &gst_report_leave ();
+
+ return 0;
+}
+
+sub gst_network_suse70_interface_activate
+{
+ my ($hash, $old_hash, $enabled, $force) = @_;
+
+ if ($force || &gst_network_interface_changed ($hash, $old_hash))
+ {
+ &gst_network_rh62_interface_activate_by_dev ($$hash{"dev"}, $enabled);
+ }
+}
+
+sub gst_network_slackware91_interface_activate_by_dev
+{
+ my ($dev, $enabled) = @_;
+ my ($address, $netmask, $gateway);
+ my ($file) = "/etc/rc.d/rc.inet1.conf";
+ my ($ret) = 0;
+
+ &gst_report_enter ();
+
+ if ($enabled)
+ {
+ &gst_report ("network_iface_activate", $dev);
+
+ if ($dev =~ /^ppp/)
+ {
+ $ret = &gst_file_run ("ppp-go");
+ }
+ else
+ {
+ if (&gst_parse_rcinet1conf_bool ($file, $dev, USE_DHCP))
+ {
+ # Use DHCP
+ $ret = &gst_file_run ("dhclient $dev");
+ }
+ else
+ {
+ $address = &gst_parse_rcinet1conf ($file, $dev, "IPADDR");
+ $netmask = &gst_parse_rcinet1conf ($file, $dev, "NETMASK");
+ $gateway = &gst_network_get_gateway ($file, "GATEWAY", $address, $netmask);
+
+ $ret = &gst_file_run ("ifconfig $dev $address netmask $netmask up");
+
+ # Add the gateway if necessary
+ if ($gateway ne undef)
+ {
+ &gst_file_run ("route add default gw $gateway");
+ }
+ }
+ }
+ }
+ else
+ {
+ &gst_report ("network_iface_deactivate", $dev);
+
+ $ret = &gst_file_run ("ifconfig $dev down") if ($dev =~ /^eth/);
+ $ret = &gst_file_run ("ppp-off") if ($dev =~ /^ppp/);
+ }
+
+ &gst_report_leave ();
+ return -1 if ($ret != 0);
+ return 0;
+}
+
+sub gst_network_slackware91_interface_activate
+{
+ my ($hash, $old_hash, $enabled, $force) = @_;
+ my $dev = $$hash{"configuration"}{"file"};
+
+ if ($force || &gst_network_interface_changed ($hash, $old_hash))
+ {
+ &gst_network_slackware91_interface_activate_by_dev ($dev, $enabled);
+ }
+}
+
+sub gst_network_gentoo_interface_activate_by_dev
+{
+ my ($dev, $enabled) = @_;
+ my $file = "/etc/init.d/net.$dev";
+ my $action = ($enabled == 1)? "start" : "stop";
+
+ return &gst_file_run ("$file $action");
+}
+
+sub gst_network_gentoo_interface_activate
+{
+ my ($hash, $old_hash, $enabled, $force) = @_;
+ my $dev = $$hash{"configuration"}{"file"};
+
+ if ($force || &gst_network_interface_changed ($hash, $old_hash))
+ {
+ &gst_network_gentoo_interface_activate_by_dev ($dev, $enabled);
+ }
+}
+
+sub gst_network_freebsd_interface_activate_by_dev
+{
+ my ($hash, $enabled) = @_;
+ my ($dev) = $$hash{"configuration"}{"file"};
+ my ($startif) = "/etc/start_if.$dev";
+ my ($file) = "/etc/rc.conf";
+ my ($command, $dhcp_flags, $defaultroute, $fd);
+
+ if ($enabled)
+ {
+ # Run the /etc/start_if.$dev commands
+ $fd = &gst_file_open_read_from_names ($startif);
+
+ while (<$fd>)
+ {
+ `$_`;
+ }
+
+ &gst_file_close ($fd);
+ $command = &gst_parse_sh ($file, "ifconfig_$dev");
+
+ # Bring up the interface
+ if ($command =~ /DHCP/i)
+ {
+ $dhcp_flags = &gst_parse_sh ($file, "dhcp_flags");
+ &gst_file_run ("dhclient $dhcp_flags $dev");
+ }
+ else
+ {
+ &gst_file_run ("ifconfig $dev $command");
+ }
+
+ # Add the default route
+ $default_route = &gst_parse_sh ($file, "defaultrouter");
+ &gst_file_run ("route add default $default_route") if ($default_route !~ /^no$/i);
+ }
+ else
+ {
+ &gst_file_run ("ifconfig $dev down");
+ }
+}
+
+sub gst_network_freebsd_interface_activate
+{
+ my ($hash, $old_hash, $enabled, $force) =@_;
+
+ if ($force || &gst_network_interface_changed ($hash, $old_hash))
+ {
+ &gst_network_freebsd_interface_activate_by_dev ($hash, $enabled);
+ }
+}
+
+sub gst_network_remove_pap_entry
+{
+ my ($file, $login) = @_;
+ my ($i, $buff);
+
+ &gst_report_enter ();
+ &gst_report ("network_remove_pap", $file, $login);
+
+ $buff = &gst_file_buffer_load ($file);
+
+ foreach $i (@$buff)
+ {
+ $i = "" if ($i =~ /^[ \t]*$login[ \t]/);
+ }
+
+ &gst_file_buffer_clean ($buff);
+ &gst_report_leave ();
+ return &gst_file_buffer_save ($buff, $file);
+}
+
+sub gst_network_rh62_interface_delete
+{
+ my ($old_hash) = @_;
+ my $dev = $$old_hash{"configuration"}{"file"};
+ my $file = "$gst_prefix/etc/sysconfig/network-scripts/ifcfg-$dev";
+ my $login;
+
+ &gst_network_rh62_interface_activate_by_dev ($dev, 0);
+
+ $login = $old_hash{"configuration"}{"login"};
+ if ($login ne "")
+ {
+ &gst_network_remove_pap_entry ("/etc/ppp/pap-secrets", $login);
+ &gst_network_remove_pap_entry ("/etc/ppp/chap-secrets", $login);
+ }
+
+ &gst_file_remove ($file);
+}
+
+sub gst_network_rh72_interface_delete
+{
+ my ($old_hash) = @_;
+ my ($dev, $login);
+
+ $filedev = $$old_hash{"configuration"}{"file"};
+ $dev = $$old_hash{"dev"};
+ $login = $$old_hash{"configuration"}{"login"};
+
+ &gst_network_rh62_interface_activate_by_dev ($filedev, 0);
+
+ if ($login ne "")
+ {
+ &gst_network_remove_pap_entry ("/etc/ppp/pap-secrets", $login);
+ &gst_network_remove_pap_entry ("/etc/ppp/chap-secrets", $login);
+ }
+
+ &gst_file_remove ("$gst_prefix/etc/sysconfig/networking/devices/ifcfg-$filedev");
+ &gst_file_remove ("$gst_prefix/etc/sysconfig/networking/profiles/default/ifcfg-$filedev");
+ &gst_file_remove ("$gst_prefix/etc/sysconfig/network-scripts/ifcfg-$dev");
+
+ &gst_file_run ("redhat-config-network-cmd");
+}
+
+sub gst_network_deb22_interface_delete
+{
+ my ($old_hash) = @_;
+ my $dev = $$old_hash{"dev"};
+
+ &gst_network_rh62_interface_activate_by_dev ($dev, 0);
+ &gst_replace_interfaces_iface_stanza_delete ("$gst_prefix/etc/network/interfaces", $dev);
+
+ $login = $old_hash{"configuration"}{"login"};
+ if ($login ne "")
+ {
+ &gst_network_remove_pap_entry ("/etc/ppp/pap-secrets", $login);
+ &gst_network_remove_pap_entry ("/etc/ppp/chap-secrets", $login);
+ }
+}
+
+sub gst_network_suse70_interface_delete
+{
+ my ($old_hash) = @_;
+ my $dev = $$old_hash{"configuration"}{"file"};
+ my $file = "$gst_prefix/etc/rc.config";
+ my $login;
+
+ &gst_network_suse70_interface_activate_by_dev ($$old_hash{"dev"}, 0);
+
+# Commented until I know what to do with ppp connections.
+# $login = $old_hash{"login"};
+# if ($login ne "")
+# {
+# &gst_network_remove_pap_entry ("/etc/ppp/pap-secrets", $login);
+# &gst_network_remove_pap_entry ("/etc/ppp/chap-secrets", $login);
+# }
+
+ &gst_replace_sh ($file, "IPADDR_$dev", "");
+ &gst_replace_sh ($file, "NETDEV_$dev", "");
+ &gst_replace_sh ($file, "IFCONFIG_$dev", "");
+}
+
+sub gst_network_suse90_interface_delete
+{
+ my ($old_hash) = @_;
+ my $file = $$old_hash{"configuration"}{"file"};
+ my $provider = &gst_parse_sh ("$gst_prefix/etc/sysconfig/network/ifcfg-$file", PROVIDER);
+ my $dev = &gst_network_suse9_get_dev_name ($file);
+
+ &gst_network_rh62_interface_activate_by_dev ($dev, 0);
+
+ &gst_file_remove ("$gst_prefix/etc/sysconfig/network/ifroute-$file");
+ &gst_file_remove ("$gst_prefix/etc/sysconfig/network/ifcfg-$file");
+ &gst_file_remove ("$gst_prefix/etc/sysconfig/network/providers/$provider");
+}
+
+sub gst_network_pld10_interface_delete
+{
+ my ($old_hash) = @_;
+ my $dev = $$old_hash{"configuration"}{"file"};
+ my $file = "$gst_prefix/etc/sysconfig/interfaces/ifcfg-$dev";
+ my $login;
+
+ &gst_network_rh62_interface_activate_by_dev ($dev, 0);
+
+ $login = $old_hash{"configuration"}{"login"};
+ if ($login ne "")
+ {
+ &gst_network_remove_pap_entry ("/etc/ppp/pap-secrets", $login);
+ &gst_network_remove_pap_entry ("/etc/ppp/chap-secrets", $login);
+ }
+
+ &gst_file_remove ($file);
+}
+
+sub gst_network_slackware91_interface_delete
+{
+ my ($old_hash) = @_;
+ my $rcinetconf = "$gst_prefix/etc/rc.d/rc.inet1.conf";
+ my $rcinet = "$gst_prefix/etc/rc.d/rc.inet1";
+ my $pppscript = "$gst_prefix/etc/ppp/pppscript";
+ my $dev = $$old_hash {"dev"};
+
+ # remove ifup/ppp-go at startup if existing
+ &gst_network_slackware91_set_auto ($rcinet, $dev);
+
+ if ($dev =~ /^eth/)
+ {
+ # empty the values
+ &gst_replace_rcinet1conf ($rcinetconf, $dev, "IPADDR", "");
+ &gst_replace_rcinet1conf ($rcinetconf, $dev, "NETMASK", "");
+ &gst_replace_rcinet1conf ($rcinetconf, $dev, "USE_DHCP", "");
+ &gst_replace_rcinet1conf ($rcinetconf, $dev, "DHCP_HOSTNAME", "");
+ }
+ elsif ($dev =~ /^ppp/)
+ {
+ &gst_file_remove ($pppscript);
+ }
+}
+
+sub gst_network_gentoo_interface_delete
+{
+ my ($old_hash) = @_;
+ my ($dev) = $$old_hash {"dev"};
+ my ($gateway) = $$old_hash {"configuration"}{"gateway"};
+ my ($initfile) = "$gst_prefix/etc/init.d/net.$dev";
+ my ($netconf);
+
+ # bring down the interface and remove from init
+ &gst_service_gentoo_set_status ($initfile, 1, 0);
+
+ if ($dev =~ /^ppp/)
+ {
+ $netconf = "/etc/conf.d/net.$dev";
+ gst_file_remove ($netconf);
+ }
+ else
+ {
+ $netconf = "/etc/conf.d/net";
+ &gst_replace_sh ($netconf, "config_$dev", "");
+ }
+}
+
+sub gst_network_freebsd_interface_delete
+{
+ my ($old_hash) = @_;
+ my ($dev) = $$old_hash{"dev"};
+ my ($startif) = "/etc/start_if.$dev";
+ my ($file) = "/etc/rc.conf";
+ my ($pppconf) = "/etc/ppp/ppp.conf";
+ my ($buff, $line_no, $end_line_no, $i);
+
+ &gst_file_run ("ifconfig $dev down");
+
+ if ($dev =~ /^tun[0-9]+/)
+ {
+ # Delete the ppp.conf section
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+
+ $buff = &gst_file_buffer_load ($pppconf);
+
+ $line_no = &gst_parse_pppconf_find_stanza ($buff, $section);
+ $end_line_no = &gst_parse_pppconf_find_next_stanza ($buff, $line_no + 1);
+ $end_line_no = scalar @$buff + 1 if ($end_line_no == -1);
+ $end_line_no--;
+
+ for ($i = $line_no; $i <= $end_line_no; $i++)
+ {
+ delete $$buff[$i];
+ }
+
+ &gst_file_buffer_clean ($buff);
+ &gst_file_buffer_save ($buff, $pppconf);
+ }
+
+ &gst_replace_sh ($file, "ifconfig_$dev", "");
+ &gst_file_remove ($startif);
+}
+
+sub gst_network_interface_changed
+{
+ my ($iface, $iface_old) = @_;
+
+ delete $$iface{"type"};
+ delete $$iface_old{"type"};
+ return !&gst_util_struct_eq ($iface, $iface_old);
+}
+
+# silly function for leveling the configuration hash
+# with the interface hash
+sub level_interface_hash
+{
+ my ($hash) = @_;
+ my (%config, $i);
+
+ $config = $$hash{"configuration"};
+
+ foreach $i (keys %$config)
+ {
+ $$hash{$i} = $$config{$i};
+ }
+}
+
+sub gst_network_interface_set
+{
+ my ($dev, $values_hash, $old_hash) = @_;
+ my (%dist_attrib, %fn);
+ my ($proc, $i, $res);
+
+ &gst_report_enter ();
+ &gst_report ("network_iface_set", $dev);
+ %dist_attrib = &gst_network_get_interface_replace_table ();
+ $proc = $dist_attrib{"iface_set"};
+ %fn = %{$dist_attrib{"fn"}};
+
+ level_interface_hash (\%$values_hash);
+ level_interface_hash (\%$old_hash);
+
+ foreach $i (keys (%fn))
+ {
+ $ {$dist_attrib{"fn"}}{$i} = &gst_parse_expand ($fn{$i}, "iface", $dev);
+ }
+
+ $res = &gst_replace_from_table ($dist_attrib{"fn"}, $dist_attrib{"table"},
+ $values_hash, $old_hash);
+
+ # if success saving the settings for the interface, set up immediatly.
+ &$proc ($values_hash, $old_hash, $$values_hash{"enabled"}, 0) if !$res;
+
+ &gst_report_leave ();
+
+ return $res;
+}
+
+sub gst_network_interfaces_set
+{
+ my ($old_hash, $values_hash) = @_;
+ my (%dist_attrib, @ifaces, %fn);
+ my ($value, $proc);
+ my ($i, $j);
+ my ($tmp, $res);
+ my ($delete_proc, $set_proc);
+ my ($was_active);
+
+ &gst_report_enter ();
+ &gst_report ("network_ifaces_set");
+
+ %dist_attrib = &gst_network_get_interface_replace_table ();
+ $old_hash = $$old_hash{"interface"};
+
+ $delete_proc = $dist_attrib{"iface_delete"};
+ $set_proc = $dist_attrib{"iface_set"};
+
+ foreach $i (keys %$values_hash)
+ {
+ # delete it if it's no longer configured
+ if (exists $$old_hash{$i}{"configuration"} &&
+ not exists $$values_hash{$i}{"configuration"})
+ {
+ &$set_proc ($$values_hash{$i}, $$old_hash{$i}, 0, 1);
+ &$delete_proc ($$old_hash{$i});
+ }
+ elsif (exists $$values_hash{$i}{"configuration"})
+ {
+ if (&gst_network_interface_changed ($$values_hash{$i}, $$old_hash{$i}))
+ {
+ $was_active = $$values_hash{$i}{"enabled"};
+
+ &$set_proc ($$values_hash{$i}, $$old_hash{$i}, 0, 1);
+ $tmp = &gst_network_interface_set ($i, $$values_hash{$i}, $$old_hash{$i});
+ $res = $tmp if !$res;
+
+ if ($was_active == 1)
+ {
+ &$set_proc ($$values_hash{$i}, $$old_hash{$i}, 1, 1);
+ }
+ }
+ }
+ }
+
+ &gst_report_leave ();
+ return $res;
+}
+
+sub gst_network_conf_set
+{
+ my $values_hash = $_[0];
+ my $old_hash;
+ my %dist_attrib;
+
+ $old_hash = &gst_network_conf_get ();
+
+ &gst_network_ensure_loopback ($values_hash, $old_hash);
+
+ %dist_attrib = &gst_network_get_replace_table ();
+ $res = &gst_replace_from_table ($dist_attrib{"fn"}, $dist_attrib{"table"},
+ $values_hash, $old_hash);
+ return $res;
+}
+
+sub gst_network_get_pap_passwd
+{
+ my ($file, $login) = @_;
+ my (@arr, $passwd);
+
+ $login = '"?' . $login . '"?';
+ &gst_report_enter ();
+ &gst_report ("network_get_pap_passwd", $login, $file);
+ $arr = &gst_parse_split_first_array ($file, $login, "[ \t]+", "[ \t]+");
+
+ $passwd = $$arr[1];
+ &gst_report_leave ();
+
+ $passwd =~ s/^\"([^\"]*)\"$/$1/;
+
+ return $passwd;
+}
+
+sub gst_network_set_pap_passwd
+{
+ my ($file, $login, $passwd) = @_;
+ my ($line);
+
+ $login = '"' . $login . '"';
+ $passwd = '"'. $passwd . '"';
+ $line = "* $passwd";
+
+ return &gst_replace_split ($file, $login, "[ \t]+", $line);
+}
+
+# These functions do not honour the file nor call directives.
+sub gst_network_get_ppp_options_re
+{
+ my ($file, $re) = @_;
+ my ($fd, @res);
+
+ &gst_report_enter ();
+ &gst_report ("network_get_ppp_option", &gst_replace_regexp_to_separator ($re), $file);
+ $fd = &gst_file_open_read_from_names ("$file");
+ &gst_report_leave ();
+ return undef if !$fd;
+
+ while (($_ = &gst_parse_chomp_line_hash_comment ($fd)) != -1)
+ {
+ $_ = $$_;
+
+ if (/$re/)
+ {
+ return $1;
+ }
+ }
+
+ return undef;
+}
+
+sub gst_network_set_ppp_options_re
+{
+ my ($file, $re, $value) = @_;
+ my ($buff, $line, $replaced, $ret);
+ my ($pre_space, $post_comment);
+
+ &gst_report_enter ();
+ &gst_report ("network_set_ppp_option", &gst_replace_regexp_to_separator ($re), $file);
+
+ $buff = &gst_file_buffer_load ($file);
+
+ foreach $line (@$buff)
+ {
+ $pre_space = $post_comment = "";
+ chomp $line;
+ $pre_space = $1 if $line =~ s/^([ \t]+)//;
+ $post_comment = $1 if $line =~ s/([ \t]*\#.*)//;
+
+ if ($line =~ /$re/)
+ {
+ $line = "$value\n";
+ $replaced = 1;
+ last;
+ }
+
+ $line = $pre_space . $line . $post_comment . "\n";
+ }
+
+ push @$buff, "$value\n" if !$replaced;
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+sub gst_network_set_ppp_options_connect
+{
+ my ($file, $value) = @_;
+ my $ret;
+
+ &gst_report_enter ();
+ &gst_report ("network_set_ppp_connect", $file);
+ $ret = &gst_network_set_ppp_options_re ($file, "^connect", "connect \"/usr/sbin/chat -v -f $value\"");
+ &gst_report_leave ();
+ return $ret;
+}
+
+sub gst_network_get_ppp_options_unsup
+{
+ my ($file) = @_;
+ my ($fd, $line, $res, $re);
+ my @known_options = ("usepeerdns", "mtu", "mru", "user", "/dev/[^ \t]+", "[0-9]+",
+ "defaultroute", "debug", "persist", "escape", "crtscts", "connect",
+ "remotename", "hide-password", "noauth", "noipdefault", "ipparam", "name \".*\"");
+
+ $res = "";
+ &gst_report_enter ();
+ &gst_report ("network_get_ppp_unsup", $file);
+ $fd = &gst_file_open_read_from_names ("$file");
+ &gst_report_leave ();
+ return undef if !$fd;
+
+ GET_LINE: while (($line = &gst_parse_chomp_line_hash_comment ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if /^[ \t]*$/;
+
+ foreach $re (@known_options)
+ {
+ next GET_LINE if /^$re/;
+ }
+
+ $res .= "$_ ";
+ }
+
+ chop $res;
+
+ return $res;
+}
+
+sub gst_network_set_ppp_options_unsup
+{
+ my ($file, $value) = @_;
+ my ($buff, $line, $re, $ret);
+ my ($pre_space, $post_comment);
+ my @known_options = ("usepeerdns", "mtu", "mru", "user", "/dev/[^ \t]+", "[0-9]+",
+ "defaultroute", "debug", "persist", "escape", "crtscts", "connect",
+ "remotename", "hide-password", "noauth", "noipdefault", "ipparam", "name \".*\"");
+
+ # The options in the last row are those that are on by default in pppd and we don't handle,
+ # so we ignore them, as they are set implicitly if not specified.
+
+ &gst_report_enter ();
+ &gst_report ("network_set_ppp_unsup", $file);
+ $buff = &gst_file_buffer_load ($file);
+
+ GET_LINE: foreach $line (@$buff)
+ {
+ $pre_space = $post_comment = "";
+ $pre_space = $1 if $line =~ s/^([ \t]+)//;
+ $post_comment = $1 if $line =~ s/([ \t]*\#.*)//;
+
+ foreach $re (@known_options)
+ {
+ next GET_LINE if $line =~ /^$re/;
+ }
+ $line = $pre_space . $post_comment . "\n";
+ $line = "" if $line =~ /^[ \t]*$/;
+ }
+
+ $value =~ s/[ \t]+([^0-9])/\n$1/g;
+ push @$buff, $value . "\n";
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+sub gst_network_rh62_parse_bootproto
+{
+ my ($file, $key) = @_;
+ my %rh62_to_proto_name =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcp",
+ "none" => "none"
+ );
+ my $ret;
+
+ $ret = &gst_parse_sh ($file, $key);
+
+ if (!exists $rh62_to_proto_name{$ret})
+ {
+ &gst_report ("network_bootproto_unsup", $file, $ret);
+ $ret = "none";
+ }
+ return $rh62_to_proto_name{$ret};
+}
+
+sub gst_network_rh62_replace_bootproto
+{
+ my ($file, $key, $value) = @_;
+ my %proto_name_to_rh62 =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcp",
+ "none" => "none"
+ );
+
+ return &gst_replace_sh ($file, $key, $proto_name_to_rh62{$value});
+}
+
+sub gst_network_deb22_parse_bootproto
+{
+ my ($file, $iface) = @_;
+ my (@stanzas, $stanza, $method, $bootproto);
+ my %debian_to_proto_name =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcp",
+ "loopback" => "none",
+ "ppp" => "none",
+ "static" => "none"
+ );
+
+ &gst_report_enter ();
+ @stanzas = &gst_parse_interfaces_stanzas ($file, "iface");
+
+ foreach $stanza (@stanzas)
+ {
+ if (($$stanza[0] eq $iface) && ($$stanza[1] eq "inet"))
+ {
+ $method = $$stanza[2];
+ last;
+ }
+ }
+
+ if (exists $debian_to_proto_name {$method})
+ {
+ $bootproto = $debian_to_proto_name {$method};
+ }
+ else
+ {
+ $bootproto = "none";
+ &gst_report ("network_bootproto_unsup", $method, $iface);
+ }
+
+ &gst_report_leave ();
+ return $bootproto;
+}
+
+sub gst_network_deb22_replace_bootproto
+{
+ my ($file, $iface, $value) = @_;
+ my (@stanzas, $stanza, $method, $bootproto);
+ my %proto_name_to_debian =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcp",
+ "loopback" => "loopback",
+ "ppp" => "ppp",
+ "none" => "static"
+ );
+
+ my %dev_to_method =
+ (
+ "lo" => "loopback",
+ "ppp" => "ppp",
+ "ippp" => "ppp"
+ );
+
+ foreach $i (keys %dev_to_method)
+ {
+ $value = $dev_to_method{$i} if $iface =~ /^$i/;
+ }
+
+ return &gst_replace_interfaces_stanza_value ($file, $iface, 2, $proto_name_to_debian{$value});
+}
+
+sub gst_network_slackware91_parse_bootproto
+{
+ my ($file, $iface) = @_;
+
+ if (&gst_parse_rcinet1conf_bool ($file, $iface, USE_DHCP))
+ {
+ return "dhcp"
+ }
+ else
+ {
+ return "none";
+ }
+}
+
+sub gst_network_slackware91_replace_bootproto
+{
+ my ($file, $iface, $value) = @_;
+
+ if ($value eq "dhcp")
+ {
+ &gst_replace_rcinet1conf ($file, $iface, USE_DHCP, "yes");
+ }
+ else
+ {
+ &gst_replace_rcinet1conf ($file, $iface, USE_DHCP);
+ }
+}
+
+sub gst_network_suse70_parse_bootproto
+{
+ my ($file, $iface) = @_;
+ my ($ret);
+ my %suse70_to_proto_name =
+ (
+ "bootp" => "bootp",
+ "dhcpclient" => "dhcp"
+ );
+
+ $ret = &gst_network_suse70_parse_iface_sh ($file, $iface, "IFCONFIG");
+ if (!exists $suse70_to_proto_name {$ret})
+ {
+ &gst_report ("network_bootproto_unsup", $iface, $ret);
+ return "none";
+ }
+
+ return $suse70_to_proto_name {$ret};
+}
+
+sub gst_network_suse70_replace_bootproto
+{
+ my ($file, $iface, $value) = @_;
+ my ($ret, $val);
+ my %proto_name_to_suse70 =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcpclient",
+ "none" => ""
+ );
+
+ $val = $proto_name_to_suse70{$value};
+ return &gst_network_suse70_replace_iface_sh ($file, $iface, "IFCONFIG", $val);
+}
+
+sub gst_network_pld10_parse_bootproto
+{
+ my ($file, $key) = @_;
+ my %pld10_to_proto_name =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcp",
+ "pump" => "pump",
+ "none" => "none"
+ );
+ my $ret;
+
+ $ret = &gst_parse_sh ($file, $key);
+
+ if (!exists $pld10_to_proto_name{$ret})
+ {
+ &gst_report ("network_bootproto_unsup", $file, $ret);
+ $ret = "none";
+ }
+ return $pld10_to_proto_name{$ret};
+}
+
+sub gst_network_pld10_replace_bootproto
+{
+ my ($file, $key, $value) = @_;
+ my %proto_name_to_pld10 =
+ (
+ "bootp" => "bootp",
+ "dhcp" => "dhcp",
+ "pump" => "pump",
+ "none" => "none"
+ );
+
+ return &gst_replace_sh ($file, $key, $proto_name_to_pld10{$value});
+}
+
+sub gst_network_parse_bootproto
+{
+ my ($file, $key) = @_;
+
+ return "dhcp" if (&gst_parse_sh ($file, $key) =~ /dhcp/i);
+ return "bootp" if (&gst_parse_sh ($file, $key) =~ /bootp/i);
+ return "none";
+}
+
+sub gst_network_suse90_replace_bootproto
+{
+ my ($file, $key, $value) = @_;
+ my %proto_name_to_suse90 =
+ (
+ "dhcp" => "dhcp",
+ "bootp" => "bootp",
+ "static" => "none",
+ );
+
+ return &gst_replace_sh ($file, $key, $proto_name_to_suse90{$value});
+}
+
+sub gst_network_gentoo_parse_bootproto
+{
+ my ($file, $dev) = @_;
+
+ return "dhcp" if (&gst_parse_confd_net ($file, "config_$dev") =~ /dhcp/i);
+ return "none";
+}
+
+sub gst_network_gentoo_replace_bootproto
+{
+ my ($file, $dev, $value) = @_;
+
+ return if ($dev =~ /^ppp/);
+
+ return &gst_replace_confd_net ($file, "config_$dev", "dhcp") if ($value ne "none");
+
+ # replace with a fake IP address, I know it's a hack
+ return &gst_replace_confd_net ($file, "config_$dev", "0.0.0.0");
+}
+
+sub gst_network_freebsd5_replace_bootproto
+{
+ my ($file, $dev, $value) = @_;
+
+ return &gst_replace_sh ($file, "ifconfig_$dev", "dhcp") if ($value ne "none");
+ return &gst_replace_sh ($file, "ifconfig_$dev", "");
+}
+
+sub gst_network_pump_iface_supported
+{
+ my ($iface) = @_;
+ my ($dev);
+ my @devs = qw(eth wlan plip irlan);
+
+ foreach $dev (@devs)
+ {
+ return 1 if $iface =~ /^$dev/;
+ }
+
+ return 0;
+}
+
+sub gst_network_parse_pppconf
+{
+ my ($pppconf, $startif, $iface, $key) = @_;
+ my ($section);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ return undef if ($section eq undef);
+
+ return &gst_parse_pppconf ($pppconf, $section, $key);
+ }
+}
+
+sub gst_network_parse_pppconf_bool
+{
+ my ($pppconf, $startif, $iface, $key) = @_;
+ my ($section);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ return undef if ($section eq undef);
+
+ return &gst_parse_pppconf_bool ($pppconf, $section, $key);
+ }
+}
+
+sub gst_network_parse_pppconf_re
+{
+ my ($pppconf, $startif, $iface, $key, $re) = @_;
+ my ($section);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ return undef if ($section eq undef);
+
+ return &gst_parse_pppconf_re ($pppconf, $section, $key, $re);
+ }
+}
+
+sub gst_network_replace_pppconf
+{
+ my ($pppconf, $startif, $iface, $key, $val) = @_;
+ my ($section);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ &gst_replace_pppconf ($pppconf, $section, $key, $val);
+ }
+}
+
+sub gst_network_replace_pppconf_bool
+{
+ my ($pppconf, $startif, $iface, $key, $val) = @_;
+ my ($section);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ &gst_replace_pppconf_bool ($pppconf, $section, $key, $val);
+ }
+}
+
+sub gst_network_replace_pppconf_route
+{
+ my ($pppconf, $startif, $iface, $key, $val) = @_;
+ my ($section);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ &gst_replace_pppconf_common ($pppconf, $section, $key,
+ ($val == 1)? "add default HISADDR" : undef);
+ }
+}
+
+sub gst_network_replace_pppconf_dial_command
+{
+ my ($pppconf, $startif, $iface, $val) = @_;
+ my ($section, $dial);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ $dial = &gst_parse_pppconf ($pppconf, $section, "dial");
+ $dial =~ s/ATD[TP]/$val/;
+
+ &gst_replace_pppconf ($pppconf, $section, "dial", $dial);
+ }
+}
+
+sub gst_network_replace_pppconf_volume
+{
+ my ($pppconf, $startif, $iface, $val) = @_;
+ my ($section, $dial, $vol, $pre, $post);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ $dial = &gst_parse_pppconf ($pppconf, $section, "dial");
+
+ if ($dial =~ /(.*AT[^ \t]*)([ML][0-3])(.* OK .*)/i)
+ {
+ $pre = $1;
+ $post = $3;
+ }
+ elsif ($dial =~ /(.*AT[^ \t]*)( OK .*)/i)
+ {
+ $pre = $1;
+ $post = $2;
+ }
+
+ if ($val == 0)
+ {
+ $vol = "M0";
+ }
+ else
+ {
+ $vol = "L$val";
+ }
+
+ $dial = $pre . $vol . $post;
+ &gst_replace_pppconf ($pppconf, $section, "dial", $dial);
+ }
+}
+
+sub gst_network_get_freebsd5_ppp_persist
+{
+ my ($startif, $iface) = @_;
+ my ($val);
+
+ if ($iface =~ /^tun[0-9]+/)
+ {
+ $val = &gst_parse_startif ($startif, "ppp[ \t]+\-(auto|ddial)[ \t]+");
+
+ return 1 if ($val eq "ddial");
+ return 0;
+ }
+
+ return undef;
+}
+
+sub gst_network_pump_get_nodns
+{
+ my ($file, $iface, $bootproto) = @_;
+
+ return undef if (!&gst_network_pump_iface_supported ($iface));
+
+ return &gst_parse_pump_get_iface_kw_not ($file, $iface, "nodns");
+}
+
+sub gst_network_pump_set_nodns
+{
+ my ($file, $iface, $bootproto, $value) = @_;
+
+ return 0 if $bootproto ne "dhcp";
+ return 0 if (!&gst_network_pump_iface_supported ($iface));
+
+ return &gst_replace_pump_iface_kw_not ($file, $iface, "nodns", $value);
+}
+
+sub gst_network_debian_parse_remote_address
+{
+ my ($file, $iface) = @_;
+ my ($str, @tuples, $tuple, @res);
+
+ &gst_report_enter ();
+ &gst_report ("network_get_remote", $iface);
+
+ @tuples = &gst_parse_interfaces_option_tuple ($file, $iface, "up", 1);
+
+ &gst_report_leave ();
+
+ foreach $tuple (@tuples)
+ {
+ @res = $$tuple[1] =~ /[ \t]+pointopoint[ \t]+([^ \t]+)/;
+ return $res[0] if $res[0];
+ }
+
+ return undef;
+}
+
+sub gst_network_debian_replace_remote_address
+{
+ my ($file, $iface, $value) = @_;
+ my ($ifconfig, $ret);
+
+ &gst_report_enter ();
+ &gst_report ("network_set_remote", $iface);
+
+ $ifconfig = &gst_file_locate_tool ("ifconfig");
+
+ $ret = &gst_replace_interfaces_option_str ($file, $iface, "up", "$ifconfig $iface pointopoint $value");
+ &gst_report_leave ();
+ return $ret;
+}
+
+sub gst_network_debian_woody_get_auto_by_stanza
+{
+ my ($file, $iface) = @_;
+ my (@stanzas, $stanza, $i);
+
+ @stanzas = &gst_parse_interfaces_stanzas ($file, "auto");
+
+ foreach $stanza (@stanzas)
+ {
+ foreach $i (@$stanza)
+ {
+ return $stanza if $i eq $iface;
+ }
+ }
+
+ return undef;
+}
+
+sub gst_network_debian_woody_get_auto
+{
+ my ($file, $iface) = @_;
+
+ return (&gst_network_debian_woody_get_auto_by_stanza ($file, $iface) ne undef)? 1 : 0;
+}
+
+sub gst_network_debian_woody_set_auto
+{
+ my ($file, $iface, $value) = @_;
+ my ($buff, $line_no, $found);
+
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+ $line_no = 0;
+
+ while (($found = &gst_replace_interfaces_get_next_stanza ($buff, \$line_no, "auto")) != -1)
+ {
+ if ($value)
+ {
+ if ($$buff[$line_no] =~ /[ \t]$iface([\# \t\n])/)
+ {
+ return &gst_file_buffer_save ($buff, $file);
+ }
+ }
+ else
+ {
+ # I'm including the hash here, although the man page says it's not supported.
+ last if $$buff[$line_no] =~ s/[ \t]$iface([\# \t\n])/$1/;
+ }
+
+ $line_no ++;
+ }
+
+ if ($found == -1)
+ {
+ if ($value)
+ {
+ &gst_replace_interfaces_auto_stanza_create ($buff, $iface);
+ }
+ }
+ else
+ {
+ if ($value)
+ {
+ chomp $$buff[$line_no];
+ $$buff[$line_no] .= " $iface\n";
+ }
+ $$buff[$line_no] =~ s/auto[ \t]*$//;
+ }
+
+ return &gst_file_buffer_save ($buff, $file);
+}
+
+# looks for eth_up $eth_iface_number
+sub gst_network_slackware91_get_auto
+{
+ my ($file, $rclocal, $iface) = @_;
+ my ($search) = 0;
+ my ($buff);
+
+ if ($iface =~ /^eth/)
+ {
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+
+ $iface =~ s/eth//;
+
+ foreach $i (@$buff)
+ {
+ if ($i =~ /^[ \t]*'start'\)/)
+ {
+ $search = 1;
+ }
+ elsif (($i =~ /^[ \t]*;;/) && ($search == 1))
+ {
+ return 0;
+ }
+ elsif (($i =~ /^[ \t]*eth_up (\S+)/) && ($search == 1))
+ {
+ return 1 if ($1 == $iface);
+ }
+ }
+
+ return 0;
+ }
+ elsif ($iface =~ /^ppp/)
+ {
+ return &gst_parse_kw ($rclocal, "ppp-go");
+ }
+}
+
+# adds or deletes eth_up $eth_iface_number
+sub gst_network_slackware91_set_auto
+{
+ my ($file, $rclocal, $iface, $active) = @_;
+ my ($search) = 0;
+ my ($nline) = 0;
+ my ($buff, $sline);
+
+ if ($iface =~ /^eth/)
+ {
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+
+ $iface =~ s/eth//;
+
+ foreach $i (@$buff)
+ {
+ if ($i =~ /^[ \t]*('start'\)|\*\))/)
+ {
+ # if the line is 'start') or *), begin the search
+ $search = 1;
+ }
+ elsif (($i =~ /^[ \t]*gateway_up/) && ($search == 1))
+ {
+ # save the line in which we're going to save the eth_up stuff
+ $sline = $nline;
+ }
+ elsif (($i =~ /^[ \t]*(;;|esac)/) && ($search == 1))
+ {
+ # we've arrived to the end of the case, if we wanted to
+ # add the iface, now it's the moment
+ $$buff[$sline] = "\teth_up $iface\n" . $$buff[$sline] if ($active == 1);
+ $search = 0;
+ }
+ elsif (($i =~ /^[ \t]*eth_up (\S+)/) && ($search == 1))
+ {
+ if ($1 == $iface)
+ {
+ delete $$buff[$nline] if ($active == 0);
+ $search = 0;
+ }
+ }
+
+ $nline++;
+ }
+
+ return &gst_file_buffer_save ($buff, $file);
+ }
+ elsif ($iface =~ /^ppp/)
+ {
+ return &gst_replace_kw ($rclocal, "ppp-go", $active);
+ }
+}
+
+# finds out if a interface is active at boot time
+sub gst_network_freebsd5_get_auto
+{
+ my ($file, $defaults_file, $iface) = @_;
+ my ($val);
+
+ $val = &gst_parse_sh ($file, "network_interfaces");
+ $val = &gst_parse_sh ($defaults_file, "network_interfaces") if ($val eq undef);
+
+ return 1 if ($val eq "auto");
+ return 1 if ($val =~ /$iface/);
+ return 0;
+}
+
+sub gst_network_freebsd5_set_auto
+{
+ my ($file, $iface, $active) = @_;
+ my ($val);
+
+ $val = &gst_parse_sh ($file, "network_interfaces");
+ $val = &gst_file_run_backtick ("ifconfig -l") if ($val =~ /auto/);
+ $val .= " ";
+
+ if ($active && ($val !~ /$iface /))
+ {
+ $val .= $iface;
+ }
+ elsif (!$active && ($val =~ /$iface /))
+ {
+ $val =~ s/$iface //;
+ }
+
+ # Trim the string
+ $val =~ s/^[ \t]*//;
+ $val =~ s/[ \t]*$//;
+
+ &gst_replace_sh ($file, "network_interfaces", $val);
+}
+
+sub gst_network_suse90_get_auto
+{
+ my ($file, $key) = @_;
+ my ($ret);
+
+ $ret = &gst_parse_sh ($file, $key);
+
+ return 1 if ($ret =~ /^onboot$/i);
+ return 0;
+}
+
+sub gst_network_suse90_set_auto
+{
+ my ($file, $key, $enabled) = @_;
+ my ($ret);
+
+ if($enabled)
+ {
+ return &gst_replace_sh($file, $key, "onboot");
+ }
+ else
+ {
+ return &gst_replace_sh($file, $key, "manual");
+ }
+}
+
+# Return IP address or netmask, depending on $what
+sub gst_network_pld10_get_ipaddr
+{
+ my ($file, $key, $what) = @_;
+ my ($ipaddr, $netmask, $ret, $i);
+ my @netmask_prefixes = (0, 128, 192, 224, 240, 248, 252, 254, 255);
+
+ $ipaddr = &gst_parse_sh($file, $key);
+ return undef if $ipaddr eq "";
+
+ if($ipaddr =~ /([^\/]*)\/([[:digit:]]*)/)
+ {
+ $netmask = $2;
+ return undef if $netmask eq "";
+
+ if($what eq "address")
+ {
+ return $1;
+ }
+
+ for($i = 0; $i < int($netmask/8); $i++)
+ {
+ $ret .= "255.";
+ }
+
+ $ret .= "$netmask_prefixes[$b%8]." if $netmask < 32;
+
+ for($i = int($netmask/8) + 1; $i < 4; $i++)
+ {
+ $ret .= "0.";
+ }
+
+ chop($ret);
+ return $ret;
+ }
+ return undef;
+}
+
+# Writes IP address or netmask, depending in $what, to $file
+sub gst_network_pld10_set_ipaddr
+{
+ my ($file, $key, $what, $value) = @_;
+ my %prefixes =
+ (
+ "0" => 0,
+ "128" => 1,
+ "192" => 2,
+ "224" => 3,
+ "240" => 4,
+ "248" => 5,
+ "252" => 6,
+ "254" => 7,
+ "255" => 8
+ );
+ my ($ipaddr, $netmask);
+
+ $ipaddr = &gst_parse_sh($file, $key);
+ return undef if $ipaddr eq "";
+
+ if($what eq "address")
+ {
+ $ipaddr =~ s/.*\//$value\//;
+ }
+ else
+ {
+ if($value =~ /([[:digit:]]*).([[:digit:]]*).([[:digit:]]*).([[:digit:]]*)/)
+ {
+ $netmask = $prefixes{$1} + $prefixes{$2} + $prefixes{$3} + $prefixes{$4};
+ $ipaddr =~ s/\/[[:digit:]]*/\/$netmask/;
+ }
+ }
+
+ return &gst_replace_sh($file, $key, $ipaddr);
+}
+
+# FIXME: this function isn't IPv6-aware
+# it checks if a IP address is in the same network than another
+sub gst_network_is_ip_in_same_network
+{
+ my ($address1, $address2, $netmask) = @_;
+ my (@add1, @add2, @mask);
+ my ($i);
+
+ return 0 if (($address1 eq undef) ||
+ ($address2 eq undef) ||
+ ($netmask eq undef));
+
+ @add1 = split (/\./, $address1);
+ @add2 = split (/\./, $address2);
+ @mask = split (/\./, $netmask);
+
+ for ($i = 0; $i < 4; $i++)
+ {
+ $add1[$i] += 0;
+ $add2[$i] += 0;
+ $mask[$i] += 0;
+
+ return 0 if (($add1[$i] & $mask[$i]) != ($add2[$i] & $mask[$i]));
+ }
+
+ return 1;
+}
+
+# function that gets a gateway device from the gateway address
+sub gst_network_get_gateway_dev_from_address
+{
+ my ($interface, $gateway) = @_;
+ my ($address, $netmask, $key);
+
+ foreach $key (keys %$interface)
+ {
+ $address = $$interface{$key}{"address"};
+ $netmask = $$interface{$key}{"netmask"};
+
+ return $$interface{$key}{"dev"} if (&gst_network_is_ip_in_same_network ($address, $gateway, $netmask));
+ }
+
+ return undef;
+}
+
+sub gst_network_get_plip_gateway
+{
+ my ($file, $key, $remote_address) = @_;
+ my ($gateway);
+
+ $gateway = &gst_parse_sh ($file, $key);
+
+ return $gateway if ($gateway eq $remote_address);
+}
+
+sub gst_network_get_gateway
+{
+ my ($file, $key, $address, $netmask) = @_;
+ my ($gateway);
+
+ return undef if ($address eq undef);
+
+ $gateway = &gst_parse_sh ($file, $key);
+
+ return $gateway if &gst_network_is_ip_in_same_network ($address, $gateway, $netmask);
+ return undef;
+}
+
+sub gst_network_suse90_get_gateway
+{
+ my ($file, $address, $netmask) = @_;
+ my ($gateway) = &gst_parse_split_first_array_pos ($file, "default", 0, "[ \t]+", "[ \t]+");
+
+ return $gateway if &gst_network_is_ip_in_same_network ($address, $gateway, $netmask);
+ return undef;
+}
+
+sub gst_network_suse90_get_plip_gateway
+{
+ my ($file, $remote_address) = @_;
+ my ($gateway) = &gst_parse_split_first_array_pos ($file, "default", 0, "[ \t]+", "[ \t]+");
+
+ return $gateway if ($gateway eq $remote_address);
+ return undef;
+}
+
+sub gst_network_suse90_replace_gateway
+{
+ my ($file, $dev, $address, $netmask, $value) = @_;
+
+
+ return &gst_replace_split ($file, "default", "[ \t]+", "$value \- $dev") if &gst_network_is_ip_in_same_network ($address, $value, $netmask);
+# return &gst_replace_split ($file, "default", "[ \t]+", "$value \- $dev") ;
+ return undef;
+
+}
+
+
+# runs a function if the interface is of type $type
+sub gst_network_check_type
+{
+ my ($iface) = shift @_;
+ my ($type) = shift @_;
+ my ($func) = shift @_;
+ my ($t);
+
+ $t = &gst_network_get_interface_type ($iface);
+
+ if ($t =~ "^$type")
+ {
+ &$func (@_);
+ }
+}
+
+# creates files neccesary for gentoo ifaces
+sub gst_network_gentoo_create_files
+{
+ my ($dev) = @_;
+ my ($init) = "/etc/init.d/net.$dev";
+ my ($conf) = "/etc/conf.d/net.$dev";
+ my ($backup) = "/etc/conf.d/net.ppp0.gstbackup";
+
+ if ($dev =~ /ppp/)
+ {
+ &gst_file_copy ("/etc/init.d/net.ppp0", $init) if (!&gst_file_exists ($init));
+
+ # backup the ppp config file
+ &gst_file_copy ("/etc/conf.d/net.ppp0", $backup) if (!&gst_file_exists ($backup));
+ &gst_file_copy ($backup, $conf) if (!&gst_file_exists ($conf));
+ }
+ else
+ {
+ &gst_file_copy ("/etc/init.d/net.eth0", $init) if (!&gst_file_exists ($init));
+ }
+
+ chmod 0755, "$gst_prefix/$init";
+}
+
+# we need this function because essid can be multiword, and thus it can't be in rc.conf
+sub gst_network_freebsd5_replace_essid
+{
+ my ($file, $startif, $iface, $essid) = @_;
+
+ if ($essid =~ /[ \t]/)
+ {
+ # It's multiword
+ &gst_file_buffer_save ("ifconfig $iface ssid \"$essid\"", $startif);
+ &gst_replace_sh_re ($file, "ifconfig_$iface", "ssid[ \t]+([^ \t]*)", "");
+ }
+ else
+ {
+ &gst_replace_sh_re ($file, "ifconfig_$iface", "ssid[ \t]+([^ \t]*)", " ssid $essid");
+ }
+}
+
+sub gst_network_freebsd_create_ppp_startif
+{
+ my ($startif, $iface, $dev, $persist) = @_;
+ my ($section);
+
+ if ($dev =~ /^tun[0-9]+/)
+ {
+ $section = &gst_parse_startif ($startif, "ppp[ \t]+\-[^ \t]+[ \t]+([^ \t]+)");
+ $section = $dev if ($section eq undef);
+
+ return &gst_file_buffer_save ("ppp -ddial $section", $startif) if ($persist eq 1);
+ return &gst_file_buffer_save ("ppp -auto $section", $startif);
+ }
+}
+
+# Functions for parsing provider file in suse 9.X
+sub gst_network_suse90_parse_provider_file_func
+{
+ my ($provider, $key, $func) = @_;
+ my ($path) = "/etc/sysconfig/network/providers/";
+
+ return &$func ("$path/$provider", $key);
+}
+
+sub gst_network_suse90_parse_provider_file
+{
+ my ($provider, $key) = @_;
+ return &gst_network_suse90_parse_provider_file_func ($provider, $key, \&gst_parse_sh);
+}
+
+sub gst_network_suse90_parse_provider_file_bool
+{
+ my ($provider, $key) = @_;
+ return &gst_network_suse90_parse_provider_file_func ($provider, $key, \&gst_parse_sh_bool);
+}
+
+# Functions for replacing in provider file in SuSE 9.X
+sub gst_network_suse90_replace_provider_file_func
+{
+ my ($provider, $key, $value, $func) = @_;
+ my ($path) = "/etc/sysconfig/network/providers/";
+
+ return &$func ("$path/$provider", $key, $value);
+}
+
+sub gst_network_suse90_replace_provider_file
+{
+ my ($provider, $key, $value) = @_;
+ #make sure the function is called only by modem
+ if ($provider =~ /ppp/)
+ {
+ return &gst_network_suse90_replace_provider_file_func ($provider, $key, $value, \&gst_replace_sh);
+ }
+}
+
+sub gst_network_suse90_replace_provider_file_bool
+{
+ my ($provider, $key, $value) = @_;
+ #make sure the function is called only by modem
+ if ($provider =~ /ppp/)
+ {
+ return &gst_network_suse90_replace_provider_file_func ($provider, $key, $value, \&gst_replace_sh_bool);
+ }
+}
+
+sub gst_network_suse9_get_dev_name
+{
+ my ($iface) = @_;
+ my ($ifaces, $dev, $hwaddr, $d);
+ my ($dev);
+
+ $dev = &gst_parse_sh ("/var/run/sysconfig/if-$iface", "interface");
+
+ if ($dev eq undef)
+ {
+ $fd = &gst_file_run_backtick ("getcfg-interface $iface");
+ }
+
+ if ($dev eq undef)
+ {
+ # Those are the last cases, we make rough guesses
+ if ($iface =~ /-pcmcia-/)
+ {
+ # it's something like wlan-pcmcia-0
+ $dev =~ s/-pcmcia-//;
+ }
+ elsif ($iface =~ /-id-([a-fA-F0-9\:]*)/)
+ {
+ # it's something like eth-id-xx:xx:xx:xx:xx:xx, which is the NIC MAC
+ $hwaddr = $1;
+ $ifaces = &gst_network_interfaces_get_info ();
+
+ foreach $d (keys %$ifaces)
+ {
+ if ($hwaddr eq $$ifaces{$d}{"hwaddr"})
+ {
+ $dev = $d;
+ last;
+ }
+ }
+ }
+ }
+
+ if ($dev eq undef)
+ {
+ # We give up, take $iface as $dev
+ $dev = $iface;
+ }
+
+ return $dev;
+}
+
+sub gst_network_detect_essids
+{
+ my ($iface) = @_;
+ my ($fd, @arr, $encrypted);
+
+ # some wireless cards need to be up before scanning
+ &gst_file_run ("ifconfig $iface up");
+ $fd = &gst_file_run_pipe_read ("iwlist $iface scanning");
+ return undef if (!$fd);
+
+ while (<$fd>)
+ {
+ if (/^[ \t]*Encryption key:([^ \t\n]+)/)
+ {
+ $encrypted = ($1 eq "off") ? 0 : 1;
+ }
+ elsif (/^[ \t]*ESSID\:"(.+)"/)
+ {
+ push @arr, {"essid" => $1,
+ "encrypted" => $encrypted };
+ }
+ }
+
+ return \@arr;
+}
+
+sub gst_network_get_wep_key_type
+{
+ my ($func) = shift @_;
+ my ($val);
+
+ $val = &$func (@_);
+
+ return undef if (!$val);
+ return "ascii" if ($val =~ /^s\:/);
+ return "hexadecimal";
+}
+
+sub gst_network_get_wep_key
+{
+ my ($func) = shift @_;
+ my ($val);
+
+ $val = &$func (@_);
+ $val =~ s/^s\://;
+
+ return $val;
+}
+
+sub gst_network_get_full_key
+{
+ my ($key, $key_type) = @_;
+
+ if ($key_type eq "ascii")
+ {
+ $key = "s:" . $key;
+ }
+
+ return $key;
+}
+
+sub gst_network_set_wep_key_type
+{
+ my ($key, $key_type, $func);
+
+ # seems kind of hackish, but we want to use distro
+ # specific saving functions, so we need to leave
+ # the args as variable as possible
+ $func = shift @_;
+ $key_type = pop @_;
+ $key = pop @_;
+
+ push @_, &gst_network_get_full_key ($key, $key_type);
+ &$func (@_);
+}
+
+# Set dist_map for your distro to "" if you don't want
+# loopback ensuring. See suse-7.0 entry for example.
+sub gst_network_ensure_loopback_interface
+{
+ my ($interface) = @_;
+ my $dev;
+ my %dist_map =
+ (
+ "redhat-5.2" => "lo",
+ "redhat-6.0" => "lo",
+ "redhat-6.1" => "lo",
+ "redhat-6.2" => "lo",
+ "redhat-7.0" => "lo",
+ "redhat-7.1" => "lo",
+ "redhat-7.2" => "lo",
+ "redhat-8.0" => "lo",
+ "redhat-9" => "",
+ "openna-1.0" => "lo",
+ "mandrake-7.1" => "lo",
+ "mandrake-7.2" => "lo",
+ "mandrake-9.0" => "lo",
+ "mandrake-9.1" => "lo",
+ "mandrake-9.2" => "lo",
+ "mandrake-10.0" => "lo",
+ "mandrake-10.1" => "lo",
+ "mandrake-10.2" => "lo",
+ "mandriva-2006.0" => "lo",
+ "mandriva-2006.1" => "lo",
+ "mandriva-2007.0" => "lo",
+ "mandriva-2007.1" => "lo",
+ "yoper-2.2" => "lo",
+ "blackpanther-4.0" => "lo",
+ "conectiva-9" => "lo",
+ "conectiva-10" => "lo",
+ "debian-2.2" => "lo",
+ "debian-3.0" => "lo",
+ "debian-3.1" => "lo",
+ "debian-4.0" => "lo",
+ "debian-5.0" => "lo",
+ "debian-testing" => "lo",
+ "ubuntu-5.04" => "lo",
+ "ubuntu-5.10" => "lo",
+ "ubuntu-6.06" => "lo",
+ "ubuntu-6.10" => "lo",
+ "ubuntu-7.04" => "lo",
+ "ubuntu-7.10" => "lo",
+ "ubuntu-8.04" => "lo",
+ "suse-7.0" => "",
+ "suse-9.0" => "",
+ "suse-9.1" => "",
+ "turbolinux-7.0" => "lo",
+ "pld-1.0" => "lo",
+ "pld-1.1" => "lo",
+ "pld-1.99" => "lo",
+ "fedora-1" => "",
+ "fedora-2" => "",
+ "fedora-3" => "",
+ "fedora-4" => "",
+ "fedora-5" => "",
+ "rpath" => "",
+ "vine-3.0" => "lo",
+ "vine-3.1" => "lo",
+ "ark" => "lo",
+ "slackware-9.1.0" => "",
+ "slackware-10.0.0" => "",
+ "slackware-10.1.0" => "",
+ "slackware-10.2.0" => "",
+ "gentoo" => "",
+ "vlos-1.2" => "",
+ "freebsd-5" => "",
+ "freebsd-6" => "",
+ );
+
+ $dev = $dist_map {$gst_dist};
+
+ return if $dev eq "";
+
+ if (!exists $$interface{$dev})
+ {
+ my %iface = (
+ "auto" => 1,
+ "user" => 0,
+ "dev" => "lo",
+ "address" => "127.0.0.1",
+ "netmask" => "255.0.0.0",
+ "broadcast" => "127.255.255.255",
+ "network" => "127.0.0.0",
+ "bootproto" => "none",
+ "enabled" => 1,
+ "update_dns" => 0
+ );
+
+ $$interface{$dev} = \%iface;
+ &gst_network_interface_set ($dev, \%iface);
+ }
+ elsif (! $ {$$interface{$dev}}{"enabled"})
+ {
+ $ {$$interface{$dev}}{"enabled"} = 1;
+ &gst_network_interface_set ($dev, $$interface{$dev});
+ }
+}
+
+sub gst_network_statichost_add_alias
+{
+ my ($localhost, $alias) = @_;
+ my $i;
+
+ foreach $i (@$localhost)
+ {
+ return if ($i eq $alias);
+ }
+
+ push @$localhost, $alias;
+}
+
+sub gst_network_statichost_remove_alias
+{
+ my ($localhost, $alias) = @_;
+ my $i;
+
+ for ($i = 0; $i < @$localhost; $i++) {
+ if ($$localhost[$i] eq $alias)
+ {
+ delete $$localhost[$i];
+ return;
+ }
+ }
+}
+
+sub gst_network_ensure_loopback_statichost
+{
+ my ($statichost, $hostname, $old_hostname, $lo_ip) = @_;
+ my $i;
+
+ if (exists $$statichost{$lo_ip})
+ {
+ my $localhost = $$statichost{$lo_ip};
+ &gst_network_statichost_remove_alias ($localhost, $old_hostname) if ($old_hostname);
+ &gst_network_statichost_add_alias ($localhost, $hostname);
+ }
+ else
+ {
+ $$statichost{$lo_ip} = [ ("localhost", "localhost.localdomain", $hostname) ];
+ }
+}
+
+sub get_network_get_lo_ip
+{
+ my ($statichost) = @_;
+
+ foreach $i (keys %$statichost)
+ {
+ return $i if ($i =~ /^127\./);
+ }
+
+ return "127.0.0.1";
+}
+
+sub gst_network_ensure_loopback
+{
+ my $values_hash = $_[0];
+ my $old_values_hash = $_[1];
+ my $interface = $$values_hash{"interface"};
+ my $hostname = $$values_hash{"hostname"};
+ my $statichost = $$values_hash{"statichost"};
+ my $lo_ip = &get_network_get_lo_ip ($statichost);
+
+ # needed for replacing hostname safely
+ my $old_hostname = $$old_values_hash{"hostname"};
+
+ &gst_report_enter ();
+ &gst_report ("network_ensure_lo");
+
+ &gst_network_ensure_loopback_statichost ($statichost, $hostname, $old_hostname, $lo_ip);
+ &gst_network_ensure_loopback_interface ($interface, $lo_ip);
+
+ &gst_report_leave ();
+}
+
+sub gst_network_get_parse_table
+{
+ my %dist_map =
+ (
+ "redhat-5.2" => "redhat-6.2",
+ "redhat-6.0" => "redhat-6.2",
+ "redhat-6.1" => "redhat-6.2",
+ "redhat-6.2" => "redhat-6.2",
+ "redhat-7.0" => "redhat-7.0",
+ "redhat-7.1" => "redhat-7.0",
+ "redhat-7.2" => "redhat-7.2",
+ "redhat-8.0" => "redhat-7.2",
+ "redhat-9" => "redhat-7.2",
+ "openna-1.0" => "redhat-6.2",
+ "mandrake-7.1" => "redhat-6.2",
+ "mandrake-7.2" => "redhat-6.2",
+ "mandrake-9.0" => "redhat-7.0",
+ "mandrake-9.1" => "redhat-7.0",
+ "mandrake-9.2" => "redhat-7.0",
+ "mandrake-10.0" => "redhat-7.0",
+ "mandrake-10.1" => "redhat-7.0",
+ "mandrake-10.2" => "redhat-7.0",
+ "mandriva-2006.0" => "redhat-7.0",
+ "mandriva-2006.1" => "redhat-7.0",
+ "mandriva-2007.0" => "redhat-7.0",
+ "mandriva-2007.1" => "redhat-7.0",
+ "yoper-2.2" => "redhat-7.0",
+ "blackpanther-4.0" => "redhat-7.0",
+ "conectiva-9" => "redhat-7.0",
+ "conectiva-10" => "redhat-7.0",
+ "debian-2.2" => "debian-2.2",
+ "debian-3.0" => "debian-2.2",
+ "debian-3.1" => "debian-2.2",
+ "debian-4.0" => "debian-2.2",
+ "debian-5.0" => "debian-2.2",
+ "debian-testing" => "debian-2.2",
+ "ubuntu-5.04" => "debian-2.2",
+ "ubuntu-5.10" => "debian-2.2",
+ "ubuntu-6.06" => "debian-2.2",
+ "ubuntu-6.10" => "debian-2.2",
+ "ubuntu-7.04" => "debian-2.2",
+ "ubuntu-7.10" => "debian-2.2",
+ "ubuntu-8.04" => "debian-2.2",
+ "suse-7.0" => "suse-7.0",
+ "suse-9.0" => "suse-9.0",
+ "suse-9.1" => "suse-9.0",
+ "turbolinux-7.0" => "redhat-7.0",
+ "pld-1.0" => "pld-1.0",
+ "pld-1.1" => "pld-1.0",
+ "pld-1.99" => "pld-1.0",
+ "fedora-1" => "redhat-7.2",
+ "fedora-2" => "redhat-7.2",
+ "fedora-3" => "redhat-7.2",
+ "fedora-4" => "redhat-7.2",
+ "fedora-5" => "redhat-7.2",
+ "rpath" => "redhat-7.2",
+ "vine-3.0" => "redhat-7.0",
+ "vine-3.1" => "redhat-7.0",
+ "ark" => "redhat-7.0",
+ "slackware-9.1.0" => "slackware-9.1.0",
+ "slackware-10.0.0" => "slackware-9.1.0",
+ "slackware-10.1.0" => "slackware-9.1.0",
+ "slackware-10.2.0" => "slackware-9.1.0",
+ "gentoo" => "gentoo",
+ "vlos-1.2" => "gentoo",
+ "freebsd-5" => "freebsd-5",
+ "freebsd-6" => "freebsd-5",
+ );
+
+ my %dist_tables =
+ (
+ "redhat-6.2" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => "/etc/sysconfig/network",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "gateway", \&gst_parse_sh, SYSCONFIG_NW, GATEWAY ],
+ [ "gatewaydev", \&gst_parse_sh, SYSCONFIG_NW, GATEWAYDEV ],
+ [ "userifacectl", \&gst_parse_trivial, 1 ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_sysv_installed, "smb" ],
+ [ "smartdhcpcd", \&gst_file_tool_installed, "pump" ],
+ [ "dialinstalled", \&gst_file_tool_installed, "wvdial" ],
+ [ "interface", \&gst_network_interfaces_get ]
+ ]
+ },
+
+ "redhat-7.0" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => "/etc/sysconfig/network",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "gateway", \&gst_parse_sh, SYSCONFIG_NW, GATEWAY ],
+ [ "gatewaydev", \&gst_parse_sh, SYSCONFIG_NW, GATEWAYDEV ],
+ [ "userifacectl", \&gst_parse_trivial, 1 ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_sysv_installed, "smb" ],
+ [ "smartdhcpcd", \&gst_file_tool_installed, "pump" ],
+ [ "dialinstalled", \&gst_file_tool_installed, "wvdial" ],
+ [ "interface", \&gst_network_interfaces_get ]
+ ]
+ },
+
+ "redhat-7.2" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => ["/etc/sysconfig/networking/profiles/default/network",
+ "/etc/sysconfig/networking/network",
+ "/etc/sysconfig/network"],
+ RESOLV_CONF => ["/etc/sysconfig/networking/profiles/default/resolv.conf",
+ "/etc/resolv.conf"],
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => ["/etc/sysconfig/networking/profiles/default/hosts",
+ "/etc/hosts"],
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf",
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "gateway", \&gst_parse_sh, SYSCONFIG_NW, GATEWAY ],
+ [ "gatewaydev", \&gst_parse_sh, SYSCONFIG_NW, GATEWAYDEV ],
+ [ "userifacectl", \&gst_parse_trivial, 1 ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_sysv_installed, "smb" ],
+ [ "smartdhcpcd", \&gst_file_tool_installed, "pump" ],
+ [ "dialinstalled", \&gst_file_tool_installed, "wvdial" ],
+ [ "interface", \&gst_network_interfaces_get ]
+ ]
+ },
+
+ "debian-2.2" =>
+ {
+ fn =>
+ {
+ OPTIONS => "/etc/network/options",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ HOSTNAME => "/etc/hostname",
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_line_first, HOSTNAME ],
+ [ "gateway", \&gst_network_get_default_gateway ],
+ [ "gatewaydev", \&gst_network_get_default_gatewaydev ],
+# [ "gwdevunsup", \&gst_parse_trivial, 1 ],
+# [ "userifacectl", \&gst_parse_trivial, 0 ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_parse_split_all_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_parse_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_sysv_installed, "samba" ],
+ [ "smartdhcpcd", \&gst_file_tool_installed, "pump" ],
+ [ "dialinstalled", \&gst_file_tool_installed, "wvdial" ],
+ [ "interface", \&gst_network_interfaces_get ]
+ ]
+ },
+
+ "suse-7.0" =>
+ {
+ fn =>
+ {
+ RC_CONFIG => "/etc/rc.config",
+ ROUTE_CONF => "/etc/route.conf",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh_get_hostname, RC_CONFIG, FQHOSTNAME ],
+ [ "gateway", \&gst_parse_split_first_str, ROUTE_CONF, "default", "[ \t]+" ],
+ [ "gateway", \&gst_parse_split_first_str, ROUTE_CONF, "0.0.0.0", "[ \t]+" ],
+ [ "gwdevunsup", \&gst_parse_trivial, 1 ],
+ [ "userifacectl", \&gst_parse_trivial, 0 ],
+ [ "domain", \&gst_parse_sh_get_domain, RC_CONFIG, FQHOSTNAME ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+# This was to take the values from SuSEConfig, but a better solution is to get
+# the configuration from /etc/resolv.conf and then replace in rc.config, so those
+# files stay in sync.
+# [ "nameserver", \&gst_parse_sh_split, RC_CONFIG, NAMESERVER, "[ \t]+" ],
+# [ "searchdomain", \&gst_parse_sh_split, RC_CONFIG, SEARCHLIST, "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_parse_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_sysv_installed, "smb" ],
+ [ "dialinstalled", \&gst_file_tool_installed, "wvdial" ],
+ [ "interface_tmp", \&gst_network_interfaces_get ],
+ [ "interface", \&gst_network_suse70_get_ppp, "%dialing%", "%interface_tmp%" ],
+ ]
+ },
+
+ "suse-9.0" =>
+ {
+ fn =>
+ {
+ ROUTE_CONF => "/etc/sysconfig/network/routes",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ HOSTNAME => "/etc/HOSTNAME",
+ SMB_CONF => "/etc/samba/smb.conf",
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_fq_hostname, HOSTNAME ],
+ [ "domain", \&gst_parse_fq_domain, HOSTNAME ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_get_status, "smb" ],
+ [ "smbinstalled", \&gst_service_installed, "smb" ],
+ [ "dialinstalled", \&gst_parse_trivial, 1 ],
+ [ "interface", \&gst_network_interfaces_get ],
+ [ "gateway", \&gst_parse_split_first_array_pos, ROUTE_CONF, "default", 0, "[ \t]+", "[ \t]+" ],
+ [ "gatewaydev", \&gst_network_get_gateway_dev_from_address, "%interface%", "%gateway%" ],
+ ]
+ },
+
+ "pld-1.0" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => "/etc/sysconfig/network",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/smb/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "gateway", \&gst_parse_sh, SYSCONFIG_NW, GATEWAY ],
+ [ "gatewaydev", \&gst_parse_sh, SYSCONFIG_NW, GATEWAYDEV ],
+ [ "userifacectl", \&gst_parse_trivial, 1 ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_sysv_installed, "smb" ],
+ [ "smartdhcpcd", \&gst_file_tool_installed, "pump" ],
+ [ "dialinstalled", \&gst_file_tool_installed, "wvdial" ],
+ [ "interface", \&gst_network_interfaces_get ]
+ ]
+ },
+
+ "slackware-9.1.0" =>
+ {
+ fn =>
+ {
+ RC_INET_CONF => "/etc/rc.d/rc.inet1.conf",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ HOSTNAME => "/etc/HOSTNAME",
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_fq_hostname, HOSTNAME ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "order", \&gst_parse_split_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_parse_split_first_bool, HOST_CONF, "multi", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_get_status_any, "smbd", "nmbd" ],
+ [ "smbinstalled", \&gst_service_installed, "/etc/rc.d/rc.samba" ],
+ [ "dialinstalled", \&gst_parse_trivial, 1 ],
+ [ "interface", \&gst_network_interfaces_get ],
+ [ "gateway", \&gst_parse_sh, RC_INET_CONF, GATEWAY ],
+ [ "gatewaydev", \&gst_network_get_gateway_dev_from_address, "%interface%", "%gateway%" ],
+ ]
+ },
+
+ "gentoo" =>
+ {
+ fn =>
+ {
+ HOSTNAME => "/etc/conf.d/hostname",
+ DOMAINNAME => "/etc/conf.d/domainname",
+ NET => "/etc/conf.d/net",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/samba/smb.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh, HOSTNAME, "HOSTNAME" ],
+ [ "domain", \&gst_parse_sh, DOMAINNAME, "DNSDOMAIN" ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_gentoo_get_status, "samba" ],
+ [ "smbinstalled", \&gst_service_installed, "samba" ],
+ [ "dialinstalled", \&gst_parse_trivial, 1 ],
+ [ "gateway", \&gst_network_get_default_gateway ],
+ [ "gatewaydev", \&gst_network_get_default_gatewaydev ],
+ [ "interface", \&gst_network_interfaces_get ],
+ ]
+ },
+
+ "freebsd-5" =>
+ {
+ fn =>
+ {
+ RC_CONF => "/etc/rc.conf",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/usr/local/etc/smb.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_parse_sh_re, RC_CONF, hostname, "^([^\.]*)\." ],
+ [ "domain", \&gst_parse_split_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_parse_split_all_unique_hash_comment, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_parse_split_first_array_unique, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "statichost", \&gst_parse_split_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_parse_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_network_rh_get_smb_desc, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_parse_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_parse_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "dialinstalled", \&gst_parse_trivial, 1 ],
+ [ "smbinstalled", \&gst_service_installed, "samba" ],
+ [ "smbuse", \&gst_service_rcng_get_status, "smbd" ],
+ [ "interface", \&gst_network_interfaces_get ],
+ [ "gateway", \&gst_parse_sh, RC_CONF, defaultrouter ],
+ [ "gatewaydev", \&gst_network_get_gateway_dev_from_address, "%interface%", "%gateway%" ],
+ ]
+ },
+ );
+
+ my $dist = $dist_map{$gst_dist};
+ return %{$dist_tables{$dist}} if $dist;
+
+ &gst_report ("platform_no_table", $gst_dist);
+ return undef;
+}
+
+sub gst_network_get_interface_parse_table
+{
+ my %dist_map =
+ (
+ "redhat-5.2" => "redhat-6.2",
+ "redhat-6.0" => "redhat-6.2",
+ "redhat-6.1" => "redhat-6.2",
+ "redhat-6.2" => "redhat-6.2",
+ "redhat-7.0" => "redhat-6.2",
+ "redhat-7.1" => "redhat-6.2",
+ "redhat-7.2" => "redhat-7.2",
+ "redhat-8.0" => "redhat-8.0",
+ "redhat-9" => "redhat-8.0",
+ "openna-1.0" => "redhat-6.2",
+ "mandrake-7.1" => "redhat-6.2",
+ "mandrake-7.2" => "redhat-6.2",
+ "mandrake-9.0" => "mandrake-9.0",
+ "mandrake-9.1" => "mandrake-9.0",
+ "mandrake-9.2" => "mandrake-9.0",
+ "mandrake-10.0" => "mandrake-9.0",
+ "mandrake-10.1" => "mandrake-9.0",
+ "mandrake-10.2" => "mandrake-9.0",
+ "mandriva-2006.0" => "mandrake-9.0",
+ "mandriva-2006.1" => "mandrake-9.0",
+ "mandriva-2007.0" => "mandrake-9.0",
+ "mandriva-2007.1" => "mandrake-9.0",
+ "yoper-2.2" => "redhat-6.2",
+ "blackpanther-4.0" => "mandrake-9.0",
+ "conectiva-9" => "conectiva-9",
+ "conectiva-10" => "conectiva-9",
+ "debian-2.2" => "debian-2.2",
+ "debian-3.0" => "debian-3.0",
+ "debian-3.1" => "debian-3.0",
+ "debian-4.0" => "debian-3.0",
+ "debian-5.0" => "debian-3.0",
+ "debian-testing" => "debian-3.0",
+ "ubuntu-5.04" => "debian-3.0",
+ "ubuntu-5.10" => "debian-3.0",
+ "ubuntu-6.06" => "debian-3.0",
+ "ubuntu-6.10" => "debian-3.0",
+ "ubuntu-7.04" => "debian-3.0",
+ "ubuntu-7.10" => "debian-3.0",
+ "ubuntu-8.04" => "debian-3.0",
+ "suse-7.0" => "suse-7.0",
+ "suse-9.0" => "suse-9.0",
+ "suse-9.1" => "suse-9.0",
+ "turbolinux-7.0" => "redhat-6.2",
+ "pld-1.0" => "pld-1.0",
+ "pld-1.1" => "pld-1.0",
+ "pld-1.99" => "pld-1.0",
+ "fedora-1" => "redhat-7.2",
+ "fedora-2" => "redhat-7.2",
+ "fedora-3" => "redhat-7.2",
+ "fedora-4" => "redhat-7.2",
+ "fedora-5" => "redhat-7.2",
+ "rpath" => "redhat-7.2",
+ "vine-3.0" => "vine-3.0",
+ "vine-3.1" => "vine-3.0",
+ "ark" => "vine-3.0",
+ "slackware-9.1.0" => "slackware-9.1.0",
+ "slackware-10.0.0" => "slackware-9.1.0",
+ "slackware-10.1.0" => "slackware-9.1.0",
+ "slackware-10.2.0" => "slackware-9.1.0",
+ "gentoo" => "gentoo",
+ "vlos-1.2" => "gentoo",
+ "freebsd-5" => "freebsd-5",
+ "freebsd-6" => "freebsd-5",
+ );
+
+ my %dist_tables =
+ (
+ "redhat-6.2" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, WVDIALSECT ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PEERDNS ]],
+ [ "mtu", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MTU ]],
+ [ "mru", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MRU ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PAPNAME ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MODEMPORT ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, LINESPEED ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, DEFROUTE ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PERSIST ]],
+ [ "serial_escapechars", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ]],
+ [ "serial_hwctl", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ ]
+ },
+
+ "redhat-7.2" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_rh72_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => ["/etc/sysconfig/networking/profiles/default/ifcfg-#iface#",
+ "/etc/sysconfig/networking/devices/ifcfg-#iface#",
+ "/etc/sysconfig/network-scripts/ifcfg-#iface#"],
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_parse_sh, IFCFG, NAME ],
+# [ "name", \&gst_parse_trivial, IFACE ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_parse_sh, IFCFG, ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, IFCFG, KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, IFCFG, KEY ]],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+ [ "section", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, WVDIALSECT ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PEERDNS ]],
+ [ "mtu", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MTU ]],
+ [ "mru", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MRU ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PAPNAME ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MODEMPORT ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, LINESPEED ]],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPOPTIONS ],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, DEFROUTE ]],
+# [ "debug", \&gst_parse_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PERSIST ]],
+ [ "serial_escapechars", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ]],
+ [ "serial_hwctl", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]],
+# [ "enabled", \&gst_network_interface_active, "%dev%",
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "redhat-8.0" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_rh72_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => ["/etc/sysconfig/networking/profiles/default/ifcfg-#iface#",
+ "/etc/sysconfig/networking/devices/ifcfg-#iface#",
+ "/etc/sysconfig/network-scripts/ifcfg-#iface#"],
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_parse_sh, IFCFG, NAME ],
+# [ "name", \&gst_parse_trivial, IFACE ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_parse_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+ [ "section", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, WVDIALSECT ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PEERDNS ]],
+ [ "mtu", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MTU ]],
+ [ "mru", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MRU ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PAPNAME ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MODEMPORT ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, LINESPEED ]],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPOPTIONS ],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, DEFROUTE ]],
+# [ "debug", \&gst_parse_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PERSIST ]],
+ [ "serial_escapechars", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ]],
+ [ "serial_hwctl", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]],
+# [ "enabled", \&gst_network_interface_active, "%dev%",
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "vine-3.0" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_parse_sh, IFCFG, NAME ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_parse_sh, IFCFG, ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, IFCFG, KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, IFCFG, KEY ]],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+ [ "section", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, WVDIALSECT ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PEERDNS ]],
+ [ "mtu", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MTU ]],
+ [ "mru", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MRU ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PAPNAME ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MODEMPORT ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, LINESPEED ]],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPOPTIONS ],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, DEFROUTE ]],
+# [ "debug", \&gst_parse_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PERSIST ]],
+ [ "serial_escapechars", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ]],
+ [ "serial_hwctl", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]],
+# [ "enabled", \&gst_network_interface_active, IFACE, \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "mandrake-9.0" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_parse_sh, IFCFG, NAME ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_parse_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+ [ "section", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, WVDIALSECT ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PEERDNS ]],
+ [ "mtu", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MTU ]],
+ [ "mru", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MRU ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PAPNAME ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MODEMPORT ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, LINESPEED ]],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPOPTIONS ],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, DEFROUTE ]],
+# [ "debug", \&gst_parse_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PERSIST ]],
+ [ "serial_escapechars", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ]],
+ [ "serial_hwctl", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "conectiva-9" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_parse_sh, IFCFG, NAME ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_parse_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+ [ "section", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, WVDIALSECT ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PEERDNS ]],
+ [ "mtu", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MTU ]],
+ [ "mru", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MRU ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PAPNAME ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, MODEMPORT ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, LINESPEED ]],
+ [ "ppp_options", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh, IFCFG, PPPOPTIONS ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, DEFROUTE ]],
+# [ "debug", \&gst_parse_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, PERSIST ]],
+ [ "serial_escapechars", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ]],
+ [ "serial_hwctl", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ]],
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_parse_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "debian-2.2" =>
+ {
+ ifaces_get => \&gst_network_debian_ifaces_get_existing,
+ fn =>
+ {
+ INTERFACES => "/etc/network/interfaces",
+ IFACE => "#iface#",
+ CHAT => "/etc/chatscripts/%section%",
+ PPP_OPTIONS => "/etc/ppp/peers/%section%",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+# [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "dev", \&gst_parse_trivial, IFACE ],
+ [ "bootproto", \&gst_network_deb22_parse_bootproto, [INTERFACES, IFACE]],
+ [ "auto", \&gst_parse_interfaces_option_kw_not, [INTERFACES, IFACE], "noauto" ],
+# [ "name", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "name" ],
+ [ "address", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "address" ],
+ [ "netmask", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "netmask" ],
+ [ "broadcast", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "broadcast" ],
+ [ "network", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "network" ],
+ [ "gateway", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "gateway" ],
+ [ "essid", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "wireless[_-]essid" ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_interfaces_option_str, INTERFACES, IFACE, "wireless[_-]key1?" ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_interfaces_option_str, INTERFACES, IFACE, "wireless[_-]key1?" ]],
+ [ "remote_address", \&gst_network_debian_parse_remote_address, [INTERFACES, IFACE]],
+ [ "section", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "provider" ],
+ [ "update_dns", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "usepeerdns" ]],
+ [ "noauth", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "noauth" ]],
+ [ "mtu", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "mtu", "[ \t]+" ]],
+ [ "mru", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "mru", "[ \t]+" ]],
+ [ "serial_port", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^(/dev/[^ \t]+)" ]],
+ [ "serial_speed", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^([0-9]+)" ]],
+ [ "login", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^login \"?([^\"]*)\"?" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "ppp_options", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_unsup, PPP_OPTIONS ]],
+ [ "set_default_gw", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "defaultroute" ]],
+ [ "debug", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "debug" ]],
+ [ "persist", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "persist" ]],
+ [ "serial_escapechars", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "escape", "[ \t]+" ]],
+ [ "serial_hwctl", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "crtscts" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "atd[^0-9]([0-9*#]*)[wW]" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "atd.*[ptwW]([0-9, -]+)" ]],
+ [ "dial_command", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "(atd[tp])[0-9, -w]+" ]],
+ [ "volume", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_modem_volume, CHAT ]],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ ]
+ },
+
+ # Basicly the same as debian-2.2, but the "auto" option changes.
+ "debian-3.0" =>
+ {
+ ifaces_get => \&gst_network_debian_ifaces_get_existing,
+ fn =>
+ {
+ INTERFACES => "/etc/network/interfaces",
+ IFACE => "#iface#",
+ CHAT => "/etc/chatscripts/%section%",
+ PPP_OPTIONS => "/etc/ppp/peers/%section%",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ },
+ table =>
+ [
+# [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "dev", \&gst_parse_trivial, IFACE ],
+ [ "bootproto", \&gst_network_deb22_parse_bootproto, [INTERFACES, IFACE]],
+ [ "auto", \&gst_network_debian_woody_get_auto, [INTERFACES, IFACE]],
+# [ "name", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "name" ],
+ [ "address", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "address" ],
+ [ "netmask", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "netmask" ],
+ [ "broadcast", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "broadcast" ],
+ [ "network", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "network" ],
+ [ "gateway", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "gateway" ],
+ [ "essid", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "wireless[_-]essid" ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_interfaces_option_str, INTERFACES, IFACE, "wireless[_-]key1?" ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_interfaces_option_str, INTERFACES, IFACE, "wireless[_-]key1?" ]],
+ [ "remote_address", \&gst_network_debian_parse_remote_address, [INTERFACES, IFACE]],
+ [ "section", \&gst_parse_interfaces_option_str, [INTERFACES, IFACE], "provider" ],
+ [ "update_dns", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_kw, PPP_OPTIONS, "usepeerdns" ]],
+ [ "noauth", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_kw, PPP_OPTIONS, "noauth" ]],
+ [ "mtu", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_split_first_str, PPP_OPTIONS, "mtu", "[ \t]+" ]],
+ [ "mru", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_split_first_str, PPP_OPTIONS, "mru", "[ \t]+" ]],
+ [ "serial_port", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^(/dev/[^ \t]+)" ]],
+ [ "serial_speed", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^([0-9]+)" ]],
+ [ "login", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^user \"?([^\"]*)\"?" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "ppp_options", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_unsup, PPP_OPTIONS ]],
+ [ "set_default_gw", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_kw, PPP_OPTIONS, "defaultroute" ]],
+ [ "debug", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_kw, PPP_OPTIONS, "debug" ]],
+ [ "persist", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_parse_kw, PPP_OPTIONS, "persist" ]],
+ [ "serial_escapechars", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "escape", "[ \t]+" ]],
+ [ "serial_hwctl", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "crtscts" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "atd[^0-9]([0-9*#]*)[wW]" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "isdn", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^number[ \t]+(.+)[wW]" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "isdn", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^number.*[wW \t](.*)" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "atd.*[ptwW]([0-9, -]+)" ]],
+ [ "dial_command", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "(atd[tp])[0-9, -w]+" ]],
+ [ "volume", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_modem_volume, CHAT ]],
+# [ "enabled", \&gst_network_interface_active, IFACE,
+# \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ ]
+ },
+
+ "suse-7.0" =>
+ {
+ ifaces_get => \&gst_network_suse70_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/rc.config",
+ IFACE => "#iface#"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_suse70_parse_bootproto, [IFCFG, IFACE] ],
+ [ "auto", \&gst_network_suse70_parse_iface_auto, [IFCFG, IFACE], NETCONFIG ],
+ [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "name", \&gst_network_suse70_parse_iface_sh, [IFCFG, IFACE], GST_IFACE_NAME ],
+ [ "dev", \&gst_network_suse70_parse_iface_sh, [IFCFG, IFACE], NETDEV ],
+ [ "address", \&gst_network_suse70_parse_iface_sh, [IFCFG, IFACE], IPADDR ],
+ [ "netmask", \&gst_network_suse70_get_ifconfig_arg, [IFCFG, IFACE], netmask ],
+ [ "broadcast", \&gst_network_suse70_get_ifconfig_arg, [IFCFG, IFACE], broadcast ],
+# [ "network", \&gst_parse_trivial, 0 ], # not supported.
+# [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ], # not supported
+ [ "remote_address", \&gst_network_suse70_get_ifconfig_arg, [IFCFG, IFACE], pointopoint ],
+ [ "enabled", \&gst_network_interface_active, IFACE,
+ \&gst_network_suse70_active_interfaces_get ],
+ [ "enabled", \&gst_parse_trivial, 0 ]
+ ]
+ },
+
+ "suse-9.0" =>
+ {
+ ifaces_get => \&gst_network_suse90_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network/ifcfg-#iface#",
+ ROUTE_CONF => "/etc/sysconfig/network/routes",
+ IFACE => "#iface#"
+ },
+ table =>
+ [
+ [ "dev", \&gst_network_suse9_get_dev_name, IFACE ],
+# [ "enabled", \&gst_network_interface_active, "%dev%", \&gst_network_active_interfaces_get ],
+ [ "auto", \&gst_network_suse90_get_auto, IFCFG, STARTMODE ],
+ [ "bootproto", \&gst_network_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "address", \&gst_parse_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_parse_sh, IFCFG, NETMASK ],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMOTE_IPADDR ],
+ [ "essid", \&gst_parse_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, IFCFG, WIRELESS_KEY ]],
+ [ "gateway", \&gst_network_suse90_get_gateway, ROUTE_CONF, "%address%", "%netmask%" ],
+ [ "gateway", \&gst_network_suse90_get_plip_gateway, ROUTE_CONF, "%remote_address%" ],
+ # Modem stuff goes here
+ [ "serial_port", \&gst_parse_sh, IFCFG, MODEM_DEVICE ],
+ [ "serial_speed", \&gst_parse_sh, IFCFG, SPEED ],
+ [ "mtu", \&gst_parse_sh, IFCFG, MTU ],
+ [ "mru", \&gst_parse_sh, IFCFG, MRU ],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPD_OPTIONS ],
+ [ "dial_command", \&gst_parse_sh, IFCFG, DIALCOMMAND ],
+ [ "external_line", \&gst_parse_sh, IFCFG, DIALPREFIX ],
+ [ "section", \&gst_parse_sh, IFCFG, PROVIDER ],
+ [ "volume", \&gst_parse_sh_re, IFCFG, INIT8, "AT.*[ml]([0-3])" ],
+ [ "login", \&gst_network_suse90_parse_provider_file, "%section%", USERNAME ],
+ [ "password", \&gst_network_suse90_parse_provider_file, "%section%", PASSWORD ],
+ [ "phone_number", \&gst_network_suse90_parse_provider_file, "%section%", PHONE ],
+ [ "dns1", \&gst_network_suse90_parse_provider_file, "%section%", DNS1 ],
+ [ "dns2", \&gst_network_suse90_parse_provider_file, "%section%", DNS2 ],
+ [ "update_dns", \&gst_network_suse90_parse_provider_file_bool, "%section%", MODIFYDNS ],
+ [ "persist", \&gst_network_suse90_parse_provider_file_bool, "%section%", PERSIST ],
+ [ "stupid", \&gst_network_suse90_parse_provider_file_bool, "%section%", STUPIDMODE ],
+ [ "set_default_gw", \&gst_network_suse90_parse_provider_file_bool, "%section%", DEFAULTROUTE ],
+ ]
+ },
+
+ "pld-1.0" =>
+ {
+ ifaces_get => \&gst_network_sysconfig_pld10_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/interfaces/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/interfaces/data/chat-#iface#",
+ IFACE => "#iface#",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_pld10_parse_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_parse_sh_bool, IFCFG, ONBOOT ],
+# [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "dev", \&gst_parse_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_network_pld10_get_ipaddr, IFCFG, IPADDR, "address" ],
+ [ "netmask", \&gst_network_pld10_get_ipaddr, IFCFG, IPADDR, "netmask" ],
+# [ "broadcast", \&gst_parse_sh, IFCFG, BROADCAST ],
+# [ "network", \&gst_parse_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ],
+ [ "remote_address", \&gst_parse_sh, IFCFG, REMIP ],
+# [ "update_dns", \&gst_network_pump_get_nodns, PUMP, "%dev%", "%bootproto%" ],
+# [ "dns1", \&gst_parse_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_parse_sh, IFCFG, DNS2 ],
+ [ "update_dns", \&gst_parse_sh_bool, IFCFG, PEERDNS ],
+ [ "mtu", \&gst_parse_sh, IFCFG, MTU ],
+ [ "mru", \&gst_parse_sh, IFCFG, MRU ],
+ [ "login", \&gst_parse_sh, IFCFG, PAPNAME ],
+ [ "password", \&gst_network_get_pap_passwd, PAP, "%login%" ],
+ [ "password", \&gst_network_get_pap_passwd, CHAP, "%login%" ],
+ [ "serial_port", \&gst_parse_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_parse_sh, IFCFG, LINESPEED ],
+# [ "ppp_options", \&gst_parse_sh, IFCFG, PPPOPTIONS ],
+# [ "section", \&gst_parse_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_parse_sh_bool, IFCFG, DEFROUTE ],
+# [ "debug", \&gst_parse_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_parse_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_parse_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_parse_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_parse_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+# [ "enabled", \&gst_network_interface_active, IFACE, \&gst_network_active_interfaces_get ],
+# [ "enabled", \&gst_parse_trivial, 0 ]
+ ]
+ },
+ "slackware-9.1.0" =>
+ {
+ ifaces_get => \&gst_network_slackware91_ifaces_get_existing,
+ fn =>
+ {
+ RC_INET_CONF => "/etc/rc.d/rc.inet1.conf",
+ RC_INET => "/etc/rc.d/rc.inet1",
+ RC_LOCAL => "/etc/rc.d/rc.local",
+ IFACE => "#iface#",
+ WIRELESS => "/etc/pcmcia/wireless.opts",
+ PPP_OPTIONS => "/etc/ppp/options",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ CHAT => "/etc/ppp/pppscript",
+ },
+ table =>
+ [
+ [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "dev", \&gst_parse_trivial, IFACE ],
+ [ "address", \&gst_parse_rcinet1conf, [RC_INET_CONF, IFACE], IPADDR ],
+ [ "netmask", \&gst_parse_rcinet1conf, [RC_INET_CONF, IFACE], NETMASK ],
+ [ "gateway", \&gst_network_get_gateway, RC_INET_CONF, GATEWAY, "%address%", "%netmask%" ],
+ [ "auto", \&gst_network_slackware91_get_auto, [RC_INET, RC_LOCAL, IFACE]],
+ [ "bootproto", \&gst_network_slackware91_parse_bootproto, [RC_INET_CONF, IFACE]],
+ [ "essid", \&gst_parse_wireless_opts, [ WIRELESS, IFACE ], \&gst_network_get_wireless_ifaces, ESSID ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_wireless_opts, WIRELESS, IFACE, \&gst_network_get_wireless_ifaces, KEY ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_wireless_opts, WIRELESS, IFACE, \&gst_network_get_wireless_ifaces, KEY ]],
+ [ "enabled", \&gst_network_interface_active, IFACE, \&gst_network_active_interfaces_get ],
+ # Modem stuff
+ [ "update_dns", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "usepeerdns" ]],
+ [ "noauth", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "noauth" ]],
+ [ "mtu", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "mtu", "[ \t]+" ]],
+ [ "mru", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "mru", "[ \t]+" ]],
+ [ "serial_port", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^(/dev/[^ \t]+)" ]],
+ [ "serial_speed", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^([0-9]+)" ]],
+ [ "login", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_re, PPP_OPTIONS, "^name \"?([^\"]*)\"?" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_pap_passwd, CHAP, "%login%" ]],
+ [ "ppp_options", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_ppp_options_unsup, PPP_OPTIONS ]],
+ [ "set_default_gw", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "defaultroute" ]],
+ [ "debug", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "debug" ]],
+ [ "persist", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "persist" ]],
+ [ "serial_escapechars", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_split_first_str, PPP_OPTIONS, "escape", "[ \t]+" ]],
+ [ "serial_hwctl", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_kw, PPP_OPTIONS, "crtscts" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "atd[^0-9]*([0-9*#]*)[wW]" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "atd.*[ptw]([0-9, -]+)" ]],
+ [ "dial_command", \&gst_network_check_type, [IFACE, "modem", \&gst_parse_chat, CHAT, "(atd[tp])[0-9, -w]+" ]],
+ [ "volume", \&gst_network_check_type, [IFACE, "modem", \&gst_network_get_modem_volume, CHAT ]],
+ ]
+ },
+
+ "gentoo" =>
+ {
+ ifaces_get => \&gst_network_gentoo_ifaces_get_existing,
+ fn =>
+ {
+ NET => "/etc/conf.d/net",
+ PPPNET => "/etc/conf.d/net.#iface#",
+ INIT => "net.#iface#",
+ IFACE => "#iface#",
+ WIRELESS => "/etc/conf.d/wireless",
+ },
+ table =>
+ [
+ [ "auto", \&gst_service_gentoo_get_service_status, INIT, "default" ],
+ [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "dev", \&gst_parse_trivial, IFACE ],
+ [ "address", \&gst_parse_confd_net_re, NET, "config_%dev%", "^[ \t]*([0-9\.]+)" ],
+ [ "netmask", \&gst_parse_confd_net_re, NET, "config_%dev%", "netmask[ \t]+([0-9\.]*)" ],
+ [ "remote_address", \&gst_parse_confd_net_re, NET, "config_%dev%", "dest_address[ \t]+([0-9\.]*)" ],
+# [ "gateway", \&gst_parse_sh_re, NET, "gateway", "%dev%/([0-9\.\:]*)" ],
+ [ "gateway", \&gst_network_gentoo_parse_gateway, [ NET, IFACE ]],
+ [ "enabled", \&gst_network_interface_active, IFACE, \&gst_network_active_interfaces_get ],
+ [ "bootproto", \&gst_network_gentoo_parse_bootproto, [ NET, IFACE ]],
+ [ "essid", \&gst_parse_sh, WIRELESS, "essid_%dev%" ],
+ [ "key_type", \&gst_network_get_wep_key_type, [ \&gst_parse_sh, WIRELESS, "key_%essid%" ]],
+ [ "key", \&gst_network_get_wep_key, [ \&gst_parse_sh, WIRELESS, "key_%essid%" ]],
+ # modem stuff
+ [ "update_dns", \&gst_parse_sh_bool, PPPNET, PEERDNS ],
+ [ "mtu", \&gst_parse_sh, PPPNET, MTU ],
+ [ "mru", \&gst_parse_sh, PPPNET, MRU ],
+ [ "serial_port", \&gst_parse_sh, PPPNET, MODEMPORT ],
+ [ "serial_speed", \&gst_parse_sh, PPPNET, LINESPEED ],
+ [ "login", \&gst_parse_sh, PPPNET, USERNAME ],
+ [ "password", \&gst_parse_sh, PPPNET, PASSWORD ],
+ [ "ppp_options", \&gst_parse_sh, PPPNET, PPPOPTIONS ],
+ [ "set_default_gw", \&gst_parse_sh_bool, PPPNET, DEFROUTE ],
+ [ "debug", \&gst_parse_sh_bool, PPPNET, DEBUG ],
+ [ "persist", \&gst_parse_sh_bool, PPPNET, PERSIST ],
+ [ "serial_escapechars", \&gst_parse_sh_bool, PPPNET, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_parse_sh_bool, PPPNET, HARDFLOWCTL ],
+ [ "external_line", \&gst_parse_sh_re, PPPNET, NUMBER, "^([0-9*#]*)wW" ],
+ [ "phone_number", \&gst_parse_sh_re, PPPNET, NUMBER, "w?([0-9]*)\$" ],
+ [ "volume", \&gst_parse_sh_re, PPPNET, INITSTRING, "^at.*[ml]([0-3])" ],
+ ]
+ },
+
+ "freebsd-5" =>
+ {
+ ifaces_get => \&gst_network_freebsd_ifaces_get_existing,
+ fn =>
+ {
+ RC_CONF => "/etc/rc.conf",
+ RC_CONF_DEFAULT => "/etc/defaults/rc.conf",
+ STARTIF => "/etc/start_if.#iface#",
+ PPPCONF => "/etc/ppp/ppp.conf",
+ IFACE => "#iface#",
+ },
+ table =>
+ [
+ [ "auto", \&gst_network_freebsd5_get_auto, [RC_CONF, RC_CONF_DEFAULT, IFACE ]],
+ [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "dev", \&gst_parse_trivial, IFACE ],
+ # we need to double check these values both in the start_if and in the rc.conf files, in this order
+ [ "address", \&gst_parse_startif, STARTIF, "inet[ \t]+([0-9\.]+)" ],
+ [ "address", \&gst_parse_sh_re, RC_CONF, "ifconfig_%dev%", "inet[ \t]+([0-9\.]+)" ],
+ [ "netmask", \&gst_parse_startif, STARTIF, "netmask[ \t]+([0-9\.]+)" ],
+ [ "netmask", \&gst_parse_sh_re, RC_CONF, "ifconfig_%dev%", "netmask[ \t]+([0-9\.]+)" ],
+ [ "remote_address", \&gst_parse_startif, STARTIF, "dest_address[ \t]+([0-9\.]+)" ],
+ [ "remote_address", \&gst_parse_sh_re, RC_CONF, "ifconfig_%dev%", "dest_address[ \t]+([0-9\.]+)" ],
+ [ "essid", \&gst_parse_startif, STARTIF, "ssid[ \t]+(\".*\"|[^\"][^ ]+)" ],
+ [ "essid", \&gst_parse_sh_re, RC_CONF, "ifconfig_%dev%", "ssid[ \t]+([^ ]*)" ],
+ # this is for plip interfaces
+ [ "gateway", \&gst_network_get_plip_gateway, RC_CONF, "defaultrouter", "%remote_address%" ],
+ [ "gateway", \&gst_network_get_gateway, RC_CONF, "defaultrouter", "%address%", "%netmask%" ],
+ [ "enabled", \&gst_network_interface_active, IFACE, \&gst_network_freebsd5_active_interfaces_get ],
+ [ "bootproto", \&gst_network_parse_bootproto, RC_CONF, "ifconfig_%dev%" ],
+ # Modem stuff
+ [ "serial_port", \&gst_network_parse_pppconf, [ PPPCONF, STARTIF, IFACE ], "device" ],
+ [ "serial_speed", \&gst_network_parse_pppconf, [ PPPCONF, STARTIF, IFACE ], "speed" ],
+ [ "mtu", \&gst_network_parse_pppconf, [ PPPCONF, STARTIF, IFACE ], "mtu" ],
+ [ "mru", \&gst_network_parse_pppconf, [ PPPCONF, STARTIF, IFACE ], "mru" ],
+ [ "login", \&gst_network_parse_pppconf, [ PPPCONF, STARTIF, IFACE ], "authname" ],
+ [ "password", \&gst_network_parse_pppconf, [ PPPCONF, STARTIF, IFACE ], "authkey" ],
+ [ "update_dns", \&gst_network_parse_pppconf_bool, [ PPPCONF, STARTIF, IFACE ], "dns" ],
+ [ "set_default_gw", \&gst_network_parse_pppconf_bool, [ PPPCONF, STARTIF, IFACE ], "default HISADDR" ],
+ [ "external_line", \&gst_network_parse_pppconf_re, [ PPPCONF, STARTIF, IFACE ], "phone", "[ \t]+([0-9]+)[wW]" ],
+ [ "phone_number", \&gst_network_parse_pppconf_re, [ PPPCONF, STARTIF, IFACE ], "phone", "[wW]?([0-9]+)[ \t]*\$" ],
+ [ "dial_command", \&gst_network_parse_pppconf_re, [ PPPCONF, STARTIF, IFACE ], "dial", "(ATD[TP])" ],
+ [ "volume", \&gst_network_parse_pppconf_re, [ PPPCONF, STARTIF, IFACE ], "dial", "AT.*[ml]([0-3]) OK " ],
+ [ "persist", \&gst_network_get_freebsd5_ppp_persist, [ STARTIF, IFACE ]],
+ ]
+ },
+ );
+
+ my $dist = $dist_map{$gst_dist};
+ return %{$dist_tables{$dist}} if $dist;
+
+ &gst_report ("platform_no_table", $gst_dist);
+ return undef;
+}
+
+sub gst_network_get_replace_table
+{
+ my %dist_map =
+ (
+ "redhat-5.2" => "redhat-5.2",
+ "redhat-6.0" => "redhat-6.2",
+ "redhat-6.1" => "redhat-6.2",
+ "redhat-6.2" => "redhat-6.2",
+ "redhat-7.0" => "redhat-7.0",
+ "redhat-7.1" => "redhat-7.0",
+ "redhat-7.2" => "redhat-7.2",
+ "redhat-8.0" => "redhat-7.2",
+ "redhat-9" => "redhat-7.2",
+ "mandrake-7.1" => "redhat-6.2",
+ "mandrake-7.2" => "redhat-6.2",
+ "mandrake-9.0" => "redhat-7.0",
+ "mandrake-9.1" => "redhat-7.0",
+ "mandrake-9.2" => "redhat-7.0",
+ "mandrake-10.0" => "redhat-7.0",
+ "mandrake-10.1" => "redhat-7.0",
+ "mandrake-10.2" => "redhat-7.0",
+ "mandriva-2006.0" => "redhat-7.0",
+ "mandriva-2006.1" => "redhat-7.0",
+ "mandriva-2007.0" => "redhat-7.0",
+ "mandriva-2007.1" => "redhat-7.0",
+ "yoper-2.2" => "redhat-7.0",
+ "blackpanther-4.0" => "redhat-7.0",
+ "conectiva-9" => "redhat-7.0",
+ "conectiva-10" => "redhat-7.0",
+ "debian-2.2" => "debian-2.2",
+ "debian-3.0" => "debian-2.2",
+ "debian-3.1" => "debian-2.2",
+ "debian-4.0" => "debian-2.2",
+ "debian-5.0" => "debian-2.2",
+ "debian-testing" => "debian-2.2",
+ "ubuntu-5.04" => "debian-2.2",
+ "ubuntu-5.10" => "debian-2.2",
+ "ubuntu-6.06" => "debian-2.2",
+ "ubuntu-6.10" => "debian-2.2",
+ "ubuntu-7.04" => "debian-2.2",
+ "ubuntu-7.10" => "debian-2.2",
+ "ubuntu-8.04" => "debian-2.2",
+ "suse-7.0" => "suse-7.0",
+ "suse-9.0" => "suse-9.0",
+ "suse-9.1" => "suse-9.0",
+ "turbolinux-7.0" => "redhat-7.0",
+ "pld-1.0" => "pld-1.0",
+ "pld-1.1" => "pld-1.0",
+ "pld-1.99" => "pld-1.0",
+ "fedora-1" => "redhat-7.2",
+ "fedora-2" => "redhat-7.2",
+ "fedora-3" => "redhat-7.2",
+ "fedora-4" => "redhat-7.2",
+ "fedora-5" => "redhat-7.2",
+ "rpath" => "redhat-7.2",
+ "vine-3.0" => "redhat-7.0",
+ "vine-3.1" => "redhat-7.0",
+ "ark" => "redhat-7.0",
+ "slackware-9.1.0" => "slackware-9.1.0",
+ "slackware-10.0.0" => "slackware-9.1.0",
+ "slackware-10.1.0" => "slackware-9.1.0",
+ "slackware-10.2.0" => "slackware-9.1.0",
+ "gentoo" => "gentoo",
+ "vlos-1.2" => "gentoo",
+ "freebsd-5" => "freebsd-5",
+ "freebsd-6" => "freebsd-5",
+ );
+
+ my %dist_tables =
+ (
+ "redhat-6.2" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => "/etc/sysconfig/network",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "auto", \&gst_replace_sh_bool, SYSCONFIG_NW, NETWORKING ],
+ [ "hostname", \&gst_replace_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_replace_sh, SYSCONFIG_NW, GATEWAY],
+ [ "gatewaydev", \&gst_replace_sh, SYSCONFIG_NW, GATEWAYDEV],
+ [ "domain", \&gst_replace_sh, SYSCONFIG_NW, DOMAIN],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_set_status, 91, "smb", "%smbuse%" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ [ "gateway", \&gst_network_route_set_default_gw, "%gatewaydev%" ]
+ ]
+ },
+
+ "redhat-7.0" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => "/etc/sysconfig/network",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "auto", \&gst_replace_sh_bool, SYSCONFIG_NW, NETWORKING ],
+ [ "hostname", \&gst_replace_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_replace_sh, SYSCONFIG_NW, GATEWAY],
+ [ "gatewaydev", \&gst_replace_sh, SYSCONFIG_NW, GATEWAYDEV],
+ [ "domain", \&gst_replace_sh, SYSCONFIG_NW, DOMAIN],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_set_status, 91, "smb", "%smbuse%" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ [ "gateway", \&gst_network_route_set_default_gw, "%gatewaydev%" ]
+ ]
+ },
+
+ "redhat-7.2" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => ["/etc/sysconfig/networking/profiles/default/network",
+ "/etc/sysconfig/networking/network",
+ "/etc/sysconfig/network"],
+ RESOLV_CONF => ["/etc/sysconfig/networking/profiles/default/resolv.conf",
+ "/etc/resolv.conf"],
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => ["/etc/sysconfig/networking/profiles/default/hosts",
+ "/etc/hosts"],
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "auto", \&gst_replace_sh_bool, SYSCONFIG_NW, NETWORKING ],
+ [ "hostname", \&gst_replace_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_replace_sh, SYSCONFIG_NW, GATEWAY],
+ [ "gatewaydev", \&gst_replace_sh, SYSCONFIG_NW, GATEWAYDEV],
+ [ "domain", \&gst_replace_sh, SYSCONFIG_NW, DOMAIN],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_set_status, 91, "smb", "%smbuse%" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ [ "gateway", \&gst_network_route_set_default_gw, "%gatewaydev%" ]
+ ]
+ },
+
+ "debian-2.2" =>
+ {
+ fn =>
+ {
+ OPTIONS => "/etc/network/options",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ HOSTNAME => "/etc/hostname",
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_replace_line_first, HOSTNAME ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_set_status, 91, "samba" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ]
+ ]
+ },
+
+ "suse-7.0" =>
+ {
+ fn =>
+ {
+ RC_CONFIG => "/etc/rc.config",
+ ROUTE_CONF => "/etc/route.conf",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/smb.conf",
+ WVDIAL => "/etc/wvdial.conf",
+ SUSECONFIG => "SuSEconfig"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_replace_sh_set_hostname, RC_CONFIG, FQHOSTNAME ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_replace_join_first_str, ROUTE_CONF, "default", "[ \t]+" ],
+ [ "gateway", \&gst_replace_join_first_str, ROUTE_CONF, "0.0.0.0", "[ \t]+" ],
+ [ "domain", \&gst_replace_sh_set_domain, RC_CONFIG, FQHOSTNAME ],
+ [ "nameserver", \&gst_replace_sh_join, RC_CONFIG, NAMESERVER, "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_sh_join, RC_CONFIG, SEARCHLIST, "[ \t]+" ],
+# Remove /etc/resolv.conf so SuSEconfig sets the new values.
+ [ "searchdomain", \&gst_file_remove, RESOLV_CONF ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_set_status, 20, "smb", "%smbuse%" ],
+ [ "interface", \&gst_network_suse70_set_ppp, [WVDIAL, "%dialing%"] ],
+# We're calling this sepparated cuz we are going to call wvdial to activate.
+ [ "interface", \&gst_network_suse70_activate_ppp ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ [ "_always_", \&gst_file_run, SUSECONFIG ],
+ ]
+ },
+
+ "suse-9.0" =>
+ {
+ fn =>
+ {
+ ROUTE_CONF => "/etc/sysconfig/network/routes",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ HOSTNAME => "/etc/HOSTNAME",
+ SMB_CONF => "/etc/samba/smb.conf",
+ },
+ table =>
+ [
+ [ "hostname", \&gst_replace_fq_hostname, HOSTNAME, "%hostname%", "%domain%" ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_suse_set_status, "smb" ],
+ [ "gateway", \&gst_replace_join_first_str, ROUTE_CONF, "default", "[ \t]+", "%gateway% - -" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ ]
+ },
+
+ "pld-1.0" =>
+ {
+ fn =>
+ {
+ SYSCONFIG_NW => "/etc/sysconfig/network",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/smb/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "auto", \&gst_replace_sh_bool, SYSCONFIG_NW, NETWORKING ],
+ [ "hostname", \&gst_replace_sh, SYSCONFIG_NW, HOSTNAME ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_replace_sh, SYSCONFIG_NW, GATEWAY],
+ [ "gatewaydev", \&gst_replace_sh, SYSCONFIG_NW, GATEWAYDEV],
+# [ "domain", \&gst_replace_sh, SYSCONFIG_NW, DOMAIN],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_sysv_set_status, 91, "smb", "%smbuse%" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ [ "gateway", \&gst_network_route_set_default_gw, "%gatewaydev%" ]
+ ]
+ },
+ "slackware-9.1.0" =>
+ {
+ fn =>
+ {
+ RC_INET_CONF => "/etc/rc.d/rc.inet1.conf",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOST_CONF => "/etc/host.conf",
+ HOSTS => "/etc/hosts",
+ HOSTNAME => "/etc/HOSTNAME",
+ SMB_CONF => "/etc/samba/smb.conf",
+ WVDIAL => "/etc/wvdial.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_replace_fq_hostname, HOSTNAME, "%hostname%", "%domain%" ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_replace_rcinet1conf_global, RC_INET_CONF, GATEWAY ],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "order", \&gst_replace_join_first_array, HOST_CONF, "order", "[ \t]+", ",[ \t]*" ],
+ [ "hostmatch", \&gst_replace_join_first_bool, HOST_CONF, "multi", "[ \t]+", "on", "off" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_bsd_set_status, "/etc/rc.d/rc.samba" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ],
+ [ "gateway", \&gst_network_route_set_default_gw, "%gatewaydev%" ]
+ ]
+ },
+
+ "gentoo" =>
+ {
+ fn =>
+ {
+ HOSTNAME => "/etc/conf.d/hostname",
+ DOMAINNAME => "/etc/conf.d/domainname",
+ NET => "/etc/conf.d/net",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/etc/samba/smb.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_replace_sh, HOSTNAME, "HOSTNAME" ],
+ [ "hostname", \&gst_network_run_hostname ],
+ [ "gateway", \&gst_network_route_set_default_gw, "%gatewaydev%" ],
+ [ "domain", \&gst_replace_sh, DOMAINNAME, "DNSDOMAIN" ],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_gentoo_set_status, "samba", 1 ],
+ # first set the gateway to something like "eth0", then add the IP address like "eth0/1.1.1.1"
+# [ "gatewaydev", \&gst_replace_sh, NET, gateway ],
+# [ "gateway", \&gst_replace_sh_re, NET, gateway, "\/[0-9\.]*\$", "/%gateway%" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ]
+ ]
+ },
+
+ "freebsd-5" =>
+ {
+ fn =>
+ {
+ RC_CONF => "/etc/rc.conf",
+ RESOLV_CONF => "/etc/resolv.conf",
+ HOSTS => "/etc/hosts",
+ SMB_CONF => "/usr/local/etc/smb.conf"
+ },
+ table =>
+ [
+ [ "hostname", \&gst_replace_sh, RC_CONF, "hostname", "%hostname%.%domain%" ],
+ [ "hostname", \&gst_network_run_hostname, "%hostname%.%domain%" ],
+ [ "domain", \&gst_replace_join_first_str, RESOLV_CONF, "domain", "[ \t]+" ],
+ [ "nameserver", \&gst_replace_join_all, RESOLV_CONF, "nameserver", "[ \t]+" ],
+ [ "searchdomain", \&gst_replace_join_first_array, RESOLV_CONF, "search", "[ \t]+", "[ \t]+" ],
+ [ "statichost", \&gst_replace_join_hash, HOSTS, "[ \t]+", "[ \t]+" ],
+ [ "workgroup", \&gst_replace_ini, SMB_CONF, "global", "workgroup" ],
+ [ "smbdesc", \&gst_replace_ini, SMB_CONF, "global", "server string", "%hostname%" ],
+ [ "winsserver", \&gst_replace_ini, SMB_CONF, "global", "wins server" ],
+ [ "winsuse", \&gst_replace_ini_bool, SMB_CONF, "global", "wins support" ],
+ [ "smbuse", \&gst_service_rcng_set_status, "samba" ],
+ [ "gateway", \&gst_replace_sh, RC_CONF, "defaultrouter" ],
+ [ "interface", \&gst_network_interfaces_set, OLD_HASH ]
+ ]
+ }
+ );
+
+ my $dist = $dist_map{$gst_dist};
+ return %{$dist_tables{$dist}} if $dist;
+
+ &gst_report ("platform_no_table", $gst_dist);
+ return undef;
+}
+
+sub gst_network_get_interface_replace_table
+{
+ my %dist_map =
+ (
+ "redhat-5.2" => "redhat-5.2",
+ "redhat-6.0" => "redhat-6.2",
+ "redhat-6.1" => "redhat-6.2",
+ "redhat-6.2" => "redhat-6.2",
+ "redhat-7.0" => "redhat-6.2",
+ "redhat-7.1" => "redhat-6.2",
+ "redhat-7.2" => "redhat-7.2",
+ "redhat-8.0" => "redhat-8.0",
+ "redhat-9" => "redhat-8.0",
+ "mandrake-7.1" => "redhat-6.2",
+ "mandrake-7.2" => "redhat-6.2",
+ "mandrake-9.0" => "mandrake-9.0",
+ "mandrake-9.1" => "mandrake-9.0",
+ "mandrake-9.2" => "mandrake-9.0",
+ "mandrake-10.0" => "mandrake-9.0",
+ "mandrake-10.1" => "mandrake-9.0",
+ "mandrake-10.2" => "mandrake-9.0",
+ "mandriva-2006.0" => "mandrake-9.0",
+ "mandriva-2006.1" => "mandrake-9.0",
+ "mandriva-2007.0" => "mandrake-9.0",
+ "mandriva-2007.1" => "mandrake-9.0",
+ "yoper-2.2" => "redhat-6.2",
+ "blackpanther-4.0" => "mandrake-9.0",
+ "conectiva-9" => "conectiva-9",
+ "conectiva-10" => "conectiva-9",
+ "debian-2.2" => "debian-2.2",
+ "debian-3.0" => "debian-3.0",
+ "debian-3.1" => "debian-3.0",
+ "debian-4.0" => "debian-3.0",
+ "debian-5.0" => "debian-3.0",
+ "debian-testing" => "debian-3.0",
+ "ubuntu-5.04" => "debian-3.0",
+ "ubuntu-5.10" => "debian-3.0",
+ "ubuntu-6.06" => "debian-3.0",
+ "ubuntu-6.10" => "debian-3.0",
+ "ubuntu-7.04" => "debian-3.0",
+ "ubuntu-7.10" => "debian-3.0",
+ "ubuntu-8.04" => "debian-3.0",
+ "suse-7.0" => "suse-7.0",
+ "suse-9.0" => "suse-9.0",
+ "suse-9.1" => "suse-9.0",
+ "turbolinux-7.0" => "redhat-6.2",
+ "pld-1.0" => "pld-1.0",
+ "pld-1.1" => "pld-1.0",
+ "pld-1.99" => "pld-1.0",
+ "fedora-1" => "redhat-7.2",
+ "fedora-2" => "redhat-7.2",
+ "fedora-3" => "redhat-7.2",
+ "fedora-4" => "redhat-7.2",
+ "fedora-5" => "redhat-7.2",
+ "rpath" => "redhat-7.2",
+ "vine-3.0" => "vine-3.0",
+ "vine-3.1" => "vine-3.0",
+ "ark" => "vine-3.0",
+ "slackware-9.1.0" => "slackware-9.1.0",
+ "slackware-10.0.0" => "slackware-9.1.0",
+ "slackware-10.1.0" => "slackware-9.1.0",
+ "slackware-10.2.0" => "slackware-9.1.0",
+ "gentoo" => "gentoo",
+ "vlos-1.2" => "gentoo",
+ "freebsd-5" => "freebsd-5",
+ "freebsd-6" => "freebsd-5",
+ );
+
+ my %dist_tables =
+ (
+ "redhat-6.2" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_rh62_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+ [ "dev", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+ [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+ [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "redhat-7.2" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_rh72_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_rh72_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => ["/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ "/etc/sysconfig/networking/profiles/default/ifcfg-#iface#",
+ "/etc/sysconfig/networking/devices/ifcfg-#iface#"],
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+ [ "name", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_replace_sh, IFCFG, ESSID ],
+ [ "key", \&gst_replace_sh, IFCFG, KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, IFCFG, KEY, "%key%" ]],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+ [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+ [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "redhat-8.0" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_rh72_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_rh72_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => ["/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ "/etc/sysconfig/networking/profiles/default/ifcfg-#iface#",
+ "/etc/sysconfig/networking/devices/ifcfg-#iface#"],
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+ [ "name", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_replace_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key", \&gst_replace_sh, IFCFG, WIRELESS_KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, IFCFG, WIRELESS_KEY, "%key%" ]],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+ [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+ [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "vine-3.0" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_rh62_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+ [ "name", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_replace_sh, IFCFG, ESSID ],
+ [ "key", \&gst_replace_sh, IFCFG, KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, IFCFG, KEY, "%key%" ]],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+ [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+ [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "mandrake-9.0" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_rh62_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+ [ "name", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_replace_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key", \&gst_replace_sh, IFCFG, WIRELESS_KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, IFCFG, WIRELESS_KEY, "%key%" ]],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+ [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+ [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "conectiva-9" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_rh62_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_rh62_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network-scripts/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/network-scripts/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_rh62_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+ [ "name", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+ [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+ [ "essid", \&gst_replace_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key", \&gst_replace_sh, IFCFG, WIRELESS_KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, IFCFG, WIRELESS_KEY, "%key%" ]],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+ [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+ [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+ [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ # wvdial settings
+ [ "phone_number", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Phone" ]],
+ [ "update_dns", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto DNS" ]],
+ [ "login", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Username" ]],
+ [ "password", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Password" ]],
+ [ "serial_port", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Modem" ]],
+ [ "serial_speed", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Baud" ]],
+ [ "set_default_gw", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Check Def Route" ]],
+ [ "persist", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Auto Reconnect" ]],
+ [ "dial_command", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Command" ]],
+ [ "external_line", \&gst_network_check_type, ["%dev%", "modem", \&gst_replace_ini, WVDIAL, "Dialer %section%", "Dial Prefix" ]],
+ ]
+ },
+
+ "debian-2.2" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate, # They use the same ifup/ifdown cmds.
+ iface_delete => \&gst_network_deb22_interface_delete,
+ ifaces_get => \&gst_network_debian_ifaces_get_existing,
+ fn =>
+ {
+ INTERFACES => "/etc/network/interfaces",
+ IFACE => "#iface#",
+ CHAT => "/etc/chatscripts/%section%",
+ PPP_OPTIONS => "/etc/ppp/peers/%section%",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+# not sup [ "user", \&gst_parse_sh_bool, IFCFG, USERCTL ],
+ [ "_always_", \&gst_network_deb22_replace_bootproto, [INTERFACES, IFACE]],
+ [ "bootproto", \&gst_network_deb22_replace_bootproto, [INTERFACES, IFACE]],
+ [ "auto", \&gst_replace_interfaces_option_kw_not, [INTERFACES, IFACE], "noauto" ],
+ [ "name", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "name" ],
+ [ "address", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "address" ],
+ [ "netmask", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "netmask" ],
+ [ "broadcast", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "broadcast" ],
+ [ "network", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "network" ],
+ [ "gateway", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "gateway" ],
+ [ "section", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "provider" ],
+ [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_kw, PPP_OPTIONS, "usepeerdns" ],
+# not sup [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+# not sup [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "noauth", \&gst_replace_kw, PPP_OPTIONS, "noauth" ],
+ [ "mtu", \&gst_replace_join_first_str, PPP_OPTIONS, "mtu", "[ \t]+" ],
+ [ "mru", \&gst_replace_join_first_str, PPP_OPTIONS, "mru", "[ \t]+" ],
+ [ "remote_address", \&gst_network_debian_replace_remote_address, [INTERFACES, IFACE]],
+ [ "login", \&gst_replace_join_first_str, PPP_OPTIONS, "user", "[ \t]+" ],
+ [ "serial_port", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^(/dev/[^ \t]+)" ],
+ [ "serial_speed", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^([0-9]+)" ],
+ [ "section", \&gst_network_set_ppp_options_connect, PPP_OPTIONS ],
+ [ "ppp_options", \&gst_network_set_ppp_options_unsup, PPP_OPTIONS ],
+ [ "set_default_gw", \&gst_replace_kw, PPP_OPTIONS, "defaultroute" ],
+ [ "debug", \&gst_replace_kw, PPP_OPTIONS, "debug" ],
+ [ "persist", \&gst_replace_kw, PPP_OPTIONS, "persist" ],
+ [ "serial_escapechars", \&gst_replace_join_first_str, PPP_OPTIONS, "escape", "[ \t]+" ],
+ [ "serial_hwctl", \&gst_replace_kw, PPP_OPTIONS, "crtscts" ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ],
+ ]
+ },
+
+ # Basicly the same as debian-2.2, but the "auto" option changes.
+ "debian-3.0" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate, # They use the same ifup/ifdown cmds.
+ iface_delete => \&gst_network_deb22_interface_delete,
+ ifaces_get => \&gst_network_debian_ifaces_get_existing,
+ fn =>
+ {
+ INTERFACES => "/etc/network/interfaces",
+ IFACE => "#iface#",
+ CHAT => "/etc/chatscripts/%section%",
+ PPP_OPTIONS => "/etc/ppp/peers/%section%",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ },
+ table =>
+ [
+ [ "_always_", \&gst_network_deb22_replace_bootproto, [INTERFACES, IFACE]],
+ [ "bootproto", \&gst_network_deb22_replace_bootproto, [INTERFACES, IFACE]],
+ [ "auto", \&gst_network_debian_woody_set_auto, [INTERFACES, IFACE]],
+ [ "address", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "address" ],
+ [ "netmask", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "netmask" ],
+ [ "gateway", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "gateway" ],
+ [ "essid", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "wireless-essid" ],
+ [ "key", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "wireless-key" ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_interfaces_option_str, INTERFACES, IFACE, "wireless-key", "%key%" ]],
+ # ugly hack for deleting undesired options (due to syntax duality)
+ [ "essid", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "wireless_essid", "" ],
+ [ "key", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "wireless_key", "" ],
+ [ "key", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "wireless_key1", "" ],
+ # End of hack
+ [ "section", \&gst_replace_interfaces_option_str, [INTERFACES, IFACE], "provider" ],
+ [ "remote_address", \&gst_network_debian_replace_remote_address, [INTERFACES, IFACE]],
+ # Modem stuff
+ [ "section", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_connect, PPP_OPTIONS ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_network_create_pppscript, CHAT ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "isdn", \&gst_network_create_isdn_options, PPP_OPTIONS ]],
+ [ "update_dns", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_kw, PPP_OPTIONS, "usepeerdns" ]],
+ [ "noauth", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_kw, PPP_OPTIONS, "noauth" ]],
+ [ "set_default_gw", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_kw, PPP_OPTIONS, "defaultroute" ]],
+ [ "debug", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_kw, PPP_OPTIONS, "debug" ]],
+ [ "persist", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_kw, PPP_OPTIONS, "persist" ]],
+ [ "serial_hwctl", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "crtscts" ]],
+ [ "mtu", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_join_first_str, PPP_OPTIONS, "mtu", "[ \t]+" ]],
+ [ "mru", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_replace_join_first_str, PPP_OPTIONS, "mru", "[ \t]+" ]],
+ [ "serial_port", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^(/dev/[^ \t]+)" ]],
+ [ "serial_speed", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^([0-9]+)" ]],
+ [ "login", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^user (.*)", "user \"%login%\"" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_network_set_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "(modem|isdn)", \&gst_network_set_pap_passwd, CHAP, "%login%" ]],
+ [ "serial_escapechars", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_join_first_str, PPP_OPTIONS, "escape", "[ \t]+" ]],
+ [ "dial_command", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_chat, CHAT, "(atd[tp])[0-9w, -]+" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_chat, CHAT, "atd[tp]([0-9w]+)" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_chat, CHAT, "atd[tp]([0-9w, -]+)", "%external_line%W%phone_number%" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "isdn", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^number (.*)", "number %phone_number%" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "isdn", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^number (.*)", "number %external_line%W%phone_number%" ]],
+ [ "volume", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_modem_volume, CHAT ]],
+ ]
+ },
+
+ "suse-7.0" =>
+ {
+ iface_set => \&gst_network_suse70_interface_activate,
+ iface_delete => \&gst_network_suse70_interface_delete,
+ ifaces_get => \&gst_network_suse70_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/rc.config",
+ IFACE => "#iface#",
+ PPP_OPTIONS => "/etc/ppp/options"
+ },
+ table =>
+ [
+# bootproto has to go second for suse, as it uses the same value for bootproto and params.
+ [ "bootproto", \&gst_network_suse70_replace_bootproto, [IFCFG, IFACE] ],
+ [ "auto", \&gst_network_suse70_replace_iface_auto, [IFCFG, IFACE], NETCONFIG ],
+ [ "dev", \&gst_network_suse70_replace_iface_sh, [IFCFG, IFACE], NETDEV ],
+# not sup [ "user", \&gst_parse_trivial, 0 ], # not supported.
+ [ "name", \&gst_network_suse70_replace_iface_sh, [IFCFG, IFACE], GST_IFACE_NAME ],
+ [ "address", \&gst_network_suse70_replace_iface_sh, [IFCFG, IFACE], IPADDR ],
+ [ "address", \&gst_network_suse70_set_ifconfig_ip, [IFCFG, IFACE] ],
+ [ "netmask", \&gst_network_suse70_set_ifconfig_arg, [IFCFG, IFACE], netmask ],
+ [ "broadcast", \&gst_network_suse70_set_ifconfig_arg, [IFCFG, IFACE], broadcast ],
+# [ "network", \&gst_parse_trivial, 0 ], # not supported.
+# [ "gateway", \&gst_parse_sh, IFCFG, GATEWAY ], # not supported
+ [ "remote_address", \&gst_network_suse70_set_ifconfig_arg, [IFCFG, IFACE], pointopoint ],
+ [ "update_dns", \&gst_replace_kw, PPP_OPTIONS, "usepeerdns" ]
+ ]
+ },
+
+ "suse-9.0" =>
+ {
+ iface_set => \&gst_network_suse9_interface_activate,
+ iface_delete => \&gst_network_suse90_interface_delete,
+ ifaces_get => \&gst_network_suse90_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/network/ifcfg-#iface#",
+ ROUTE_CONF => "/etc/sysconfig/network/routes",
+ IFACE => "#iface#",
+ PPP_OPTIONS => "/etc/ppp/options"
+ },
+ table =>
+ [
+ [ "auto", \&gst_network_suse90_set_auto, IFCFG, STARTMODE ],
+ [ "bootproto", \&gst_network_suse90_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "address", \&gst_replace_sh, IFCFG, IPADDR ],
+ [ "netmask", \&gst_replace_sh, IFCFG, NETMASK ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMOTE_IPADDR ],
+ [ "essid", \&gst_replace_sh, IFCFG, WIRELESS_ESSID ],
+ [ "key", \&gst_replace_sh, IFCFG, WIRELESS_KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, IFCFG, WIRELESS_KEY, "%key%" ]],
+ # Modem stuff goes here
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEM_DEVICE ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, SPEED ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPD_OPTIONS ],
+ [ "dial_command", \&gst_replace_sh, IFCFG, DIALCOMMAND ],
+ [ "external_line", \&gst_replace_sh, IFCFG, DIALPREFIX ],
+ [ "provider", \&gst_replace_sh, IFCFG, PROVIDER ],
+ [ "volume", \&gst_network_check_type, [ IFACE, "modem", \&gst_network_set_modem_volume_string, IFCFG, INIT8 ]],
+ [ "login", \&gst_network_suse90_replace_provider_file, "%provider%", USERNAME ],
+ [ "password", \&gst_network_suse90_replace_provider_file, "%provider%", PASSWORD ],
+ [ "phone_number", \&gst_network_suse90_replace_provider_file, "%provider%", PHONE ],
+ [ "dns1", \&gst_network_suse90_replace_provider_file, "%provider%", DNS1 ],
+ [ "dns2", \&gst_network_suse90_replace_provider_file, "%provider%", DNS2 ],
+ [ "update_dns", \&gst_network_suse90_replace_provider_file_bool, "%provider%", MODIFYDNS ],
+ [ "stupid", \&gst_network_suse90_replace_provider_file_bool, "%provider%", STUPIDMODE ],
+ [ "persist", \&gst_network_suse90_replace_provider_file_bool, "%provider%", PERSIST ],
+ [ "set_default_gw", \&gst_network_suse90_replace_provider_file_bool, "%provider%", DEFAULTROUTE ],
+ ]
+ },
+
+ "pld-1.0" =>
+ {
+ iface_set => \&gst_network_rh62_interface_activate,
+ iface_delete => \&gst_network_pld10_interface_delete,
+ ifaces_get => \&gst_network_sysconfig_pld10_ifaces_get_existing,
+ fn =>
+ {
+ IFCFG => "/etc/sysconfig/interfaces/ifcfg-#iface#",
+ CHAT => "/etc/sysconfig/interfaces/data/chat-#iface#",
+ IFACE => "#iface#",
+ WVDIAL => "/etc/wvdial.conf",
+ PUMP => "/etc/pump.conf"
+ },
+ table =>
+ [
+ [ "bootproto", \&gst_network_pld10_replace_bootproto, IFCFG, BOOTPROTO ],
+ [ "auto", \&gst_replace_sh_bool, IFCFG, ONBOOT ],
+ [ "user", \&gst_replace_sh_bool, IFCFG, USERCTL ],
+# [ "name", \&gst_replace_sh, IFCFG, NAME ],
+ [ "dev", \&gst_replace_sh, IFCFG, DEVICE ],
+ [ "address", \&gst_network_pld10_set_ipaddr, IFCFG, IPADDR, "address" ],
+ [ "netmask", \&gst_network_pld10_set_ipaddr, IFCFG, IPADDR, "netmask" ],
+# [ "broadcast", \&gst_replace_sh, IFCFG, BROADCAST ],
+# [ "network", \&gst_replace_sh, IFCFG, NETWORK ],
+ [ "gateway", \&gst_replace_sh, IFCFG, GATEWAY ],
+# [ "update_dns", \&gst_network_pump_set_nodns, PUMP, "%dev%", "%bootproto%" ],
+ [ "update_dns", \&gst_replace_sh_bool, IFCFG, PEERDNS ],
+# [ "dns1", \&gst_replace_sh, IFCFG, DNS1 ],
+# [ "dns2", \&gst_replace_sh, IFCFG, DNS2 ],
+ [ "mtu", \&gst_replace_sh, IFCFG, MTU ],
+ [ "mru", \&gst_replace_sh, IFCFG, MRU ],
+ [ "remote_address", \&gst_replace_sh, IFCFG, REMIP ],
+ [ "login", \&gst_replace_sh, IFCFG, PAPNAME ],
+ [ "serial_port", \&gst_replace_sh, IFCFG, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, IFCFG, LINESPEED ],
+ [ "ppp_options", \&gst_replace_sh, IFCFG, PPPOPTIONS ],
+# [ "section", \&gst_replace_sh, IFCFG, WVDIALSECT ],
+ [ "set_default_gw", \&gst_replace_sh_bool, IFCFG, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, IFCFG, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, IFCFG, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, IFCFG, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, IFCFG, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_chat, CHAT, "^atd[^0-9]*([0-9, -]+)" ]
+ ]
+ },
+
+ "slackware-9.1.0" =>
+ {
+ iface_set => \&gst_network_slackware91_interface_activate,
+ iface_delete => \&gst_network_slackware91_interface_delete,
+ ifaces_get => \&gst_network_slackware91_ifaces_get_existing,
+ fn =>
+ {
+ RC_INET_CONF => "/etc/rc.d/rc.inet1.conf",
+ RC_INET => "/etc/rc.d/rc.inet1",
+ RC_LOCAL => "/etc/rc.d/rc.local",
+ IFACE => "#iface#",
+ WIRELESS => "/etc/pcmcia/wireless.opts",
+ PPP_OPTIONS => "/etc/ppp/options",
+ PAP => "/etc/ppp/pap-secrets",
+ CHAP => "/etc/ppp/chap-secrets",
+ CHAT => "/etc/ppp/pppscript",
+ },
+ table =>
+ [
+ [ "address", \&gst_replace_rcinet1conf, [ RC_INET_CONF, IFACE ], IPADDR ],
+ [ "netmask", \&gst_replace_rcinet1conf, [ RC_INET_CONF, IFACE ], NETMASK ],
+ [ "gateway", \&gst_replace_rcinet1conf_global, RC_INET_CONF, GATEWAY ],
+ [ "bootproto", \&gst_network_slackware91_replace_bootproto, [ RC_INET_CONF, IFACE ] ],
+ [ "auto", \&gst_network_slackware91_set_auto, [ RC_INET, RC_LOCAL, IFACE ] ],
+ [ "essid", \&gst_replace_wireless_opts, [ WIRELESS, IFACE ], \&gst_network_get_wireless_ifaces, ESSID ],
+ [ "key", \&gst_replace_wireless_opts, [ WIRELESS, IFACE ], \&gst_network_get_wireless_ifaces, KEY ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_wireless_opts, [ WIRELESS, IFACE ], \&gst_network_get_wireless_ifaces, KEY, "%key%" ]],
+ # Modem stuff
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_network_create_pppscript, CHAT ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_network_slackware91_create_pppgo ]],
+ [ "update_dns", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "usepeerdns" ]],
+ [ "noauth", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "noauth" ]],
+ [ "set_default_gw", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "defaultroute" ]],
+ [ "debug", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "debug" ]],
+ [ "persist", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "persist" ]],
+ [ "serial_hwctl", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_kw, PPP_OPTIONS, "crtscts" ]],
+ [ "mtu", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_join_first_str, PPP_OPTIONS, "mtu", "[ \t]+" ]],
+ [ "mru", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_join_first_str, PPP_OPTIONS, "mru", "[ \t]+" ]],
+ [ "serial_port", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^(/dev/[^ \t]+)" ]],
+ [ "serial_speed", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^([0-9]+)" ]],
+ [ "login", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_re, PPP_OPTIONS, "^name \"(.*)\"", "name \"%login%\"" ]],
+ [ "ppp_options", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_ppp_options_unsup, PPP_OPTIONS ]],
+ [ "serial_escapechars", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_join_first_str, PPP_OPTIONS, "escape", "[ \t]+" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_pap_passwd, PAP, "%login%" ]],
+ [ "password", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_pap_passwd, CHAP, "%login%" ]],
+ [ "dial_command", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_chat, CHAT, "(atd[tp])[0-9w, -]+" ]],
+ [ "phone_number", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_chat, CHAT, "atd[tp]([0-9w]+)" ]],
+ [ "external_line", \&gst_network_check_type, [IFACE, "modem", \&gst_replace_chat, CHAT, "atd[tp]([0-9w, -]+)", "%external_line%W%phone_number%" ]],
+ [ "volume", \&gst_network_check_type, [IFACE, "modem", \&gst_network_set_modem_volume, CHAT ]],
+ ]
+ },
+
+ "gentoo" =>
+ {
+ iface_set => \&gst_network_gentoo_interface_activate,
+ iface_delete => \&gst_network_gentoo_interface_delete,
+ ifaces_get => \&gst_network_gentoo_ifaces_get_existing,
+ fn =>
+ {
+ NET => "/etc/conf.d/net",
+ PPPNET => "/etc/conf.d/net.#iface#",
+ INIT => "net.#iface#",
+ IFACE => "#iface#",
+ WIRELESS => "/etc/conf.d/wireless",
+ },
+ table =>
+ [
+ [ "dev", \&gst_network_gentoo_create_files ],
+ [ "auto", \&gst_service_gentoo_set_status, INIT , 0 ],
+ [ "bootproto", \&gst_network_gentoo_replace_bootproto, [ NET, IFACE ]],
+ [ "address", \&gst_replace_confd_net_re, NET, "config_%dev%", "^[ \t]*([0-9\.]+)" ],
+ [ "address", \&gst_replace_confd_net_re, NET, "config_%dev%", "^[ \t]*([0-9\.]+)" ],
+ [ "netmask", \&gst_replace_confd_net_re, NET, "config_%dev%", "[ \t]+netmask[ \t]+[0-9\.]*", " netmask %netmask%"],
+ [ "broadcast", \&gst_replace_confd_net_re, NET, "config_%dev%", "[ \t]+broadcast[ \t]+[0-9\.]*", " broadcast %broadcast%" ],
+ [ "remote_address", \&gst_replace_confd_net_re, NET, "config_%dev%", "[ \t]+dest_address[ \t]+[0-9\.]*", " dest_address %remote_address%" ],
+ [ "gateway", \&gst_replace_confd_net_re, NET, "routes_%dev%", "[ \t]*default[ \t]+(via|gw)[ \t]+[0-9\.\:]*", "default via %gateway%" ],
+ [ "essid", \&gst_replace_sh, WIRELESS, "essid_%dev%" ],
+ [ "key", \&gst_replace_sh, WIRELESS, "key_%essid%" ],
+ [ "key_type", \&gst_network_set_wep_key_type, [ \&gst_replace_sh, WIRELESS, "key_%essid%", "%key%" ]],
+ # modem stuff
+ [ "dev", \&gst_network_check_type, [ IFACE, "modem", \&gst_replace_sh, PPPNET, PEER ]],
+ [ "update_dns", \&gst_network_check_type, [ IFACE, "modem", \&gst_replace_sh_bool, PPPNET, PEERDNS ]],
+ [ "mtu", \&gst_replace_sh, PPPNET, MTU ],
+ [ "mru", \&gst_replace_sh, PPPNET, MRU ],
+ [ "serial_port", \&gst_replace_sh, PPPNET, MODEMPORT ],
+ [ "serial_speed", \&gst_replace_sh, PPPNET, LINESPEED ],
+ [ "login", \&gst_replace_sh, PPPNET, USERNAME ],
+ [ "password", \&gst_replace_sh, PPPNET, PASSWORD ],
+ [ "ppp_options", \&gst_replace_sh, PPPNET, PPPOPTIONS ],
+ [ "set_default_gw", \&gst_replace_sh_bool, PPPNET, DEFROUTE ],
+ [ "debug", \&gst_replace_sh_bool, PPPNET, DEBUG ],
+ [ "persist", \&gst_replace_sh_bool, PPPNET, PERSIST ],
+ [ "serial_escapechars", \&gst_replace_sh_bool, PPPNET, ESCAPECHARS ],
+ [ "serial_hwctl", \&gst_replace_sh_bool, PPPNET, HARDFLOWCTL ],
+ [ "phone_number", \&gst_replace_sh, PPPNET, NUMBER ],
+ [ "external_line", \&gst_replace_sh, PPPNET, NUMBER, "%external_line%W%phone_number%" ],
+ [ "volume", \&gst_network_set_modem_volume_string, PPPNET, INITSTRING ],
+ ]
+ },
+
+ "freebsd-5" =>
+ {
+ iface_set => \&gst_network_freebsd_interface_activate,
+ iface_delete => \&gst_network_freebsd_interface_delete,
+ ifaces_get => \&gst_network_freebsd_ifaces_get_existing,
+ fn =>
+ {
+ RC_CONF => "/etc/rc.conf",
+ STARTIF => "/etc/start_if.#iface#",
+ PPPCONF => "/etc/ppp/ppp.conf",
+ IFACE => "#iface#",
+ },
+ table =>
+ [
+ [ "auto", \&gst_network_freebsd5_set_auto, [ RC_CONF, IFACE ]],
+ [ "bootproto", \&gst_network_freebsd5_replace_bootproto, [ RC_CONF, IFACE ]],
+ [ "address", \&gst_replace_sh_re, RC_CONF, "ifconfig_%dev%", "inet[ \t]+([0-9\.]+)", "inet %address%" ],
+ [ "netmask", \&gst_replace_sh_re, RC_CONF, "ifconfig_%dev%", "netmask[ \t]+([0-9\.]+)", " netmask %netmask%" ],
+ [ "remote_address", \&gst_replace_sh_re, RC_CONF, "ifconfig_%dev%", "dest_address[ \t]+([0-9\.]+)", " dest_address %remote_address%" ],
+ [ "essid", \&gst_network_freebsd5_replace_essid, [ RC_CONF, STARTIF, IFACE ]],
+ # Modem stuff
+ # we need this for putting an empty ifconfig_tunX command in rc.conf
+ [ "phone_number", \&gst_replace_sh, RC_CONF, "ifconfig_%dev%", " " ],
+ [ "file", \&gst_network_freebsd_create_ppp_startif, [ STARTIF, IFACE ]],
+ [ "persist", \&gst_network_freebsd_create_ppp_startif, [ STARTIF, IFACE ], "%file%" ],
+ [ "serial_port", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "device" ],
+ [ "serial_speed", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "speed" ],
+ [ "mtu", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "mtu" ],
+ [ "mru", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "mru" ],
+ [ "login", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "authname" ],
+ [ "password", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "authkey" ],
+ [ "update_dns", \&gst_network_replace_pppconf_bool, [ PPPCONF, STARTIF, IFACE ], "dns" ],
+ [ "set_default_gw", \&gst_network_replace_pppconf_route, [ PPPCONF, STARTIF, IFACE ], "default HISADDR" ],
+ [ "phone_number", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "phone" ],
+ [ "external_line", \&gst_network_replace_pppconf, [ PPPCONF, STARTIF, IFACE ], "phone", "%external_line%W%phone_number%" ],
+ [ "dial_command", \&gst_network_replace_pppconf_dial_command, [ PPPCONF, STARTIF, IFACE ]],
+ [ "volume", \&gst_network_replace_pppconf_volume, [ PPPCONF, STARTIF, IFACE ]],
+ ]
+ }
+ );
+
+ my $dist = $dist_map{$gst_dist};
+ return %{$dist_tables{$dist}} if $dist;
+
+ &gst_report ("platform_no_table", $gst_dist);
+ return undef;
+}
+
+1;
diff --git a/knetworkconf/backends/parse.pl.in b/knetworkconf/backends/parse.pl.in
new file mode 100644
index 0000000..9bad7d8
--- /dev/null
+++ b/knetworkconf/backends/parse.pl.in
@@ -0,0 +1,1828 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# parse.pl: Common parsing stuff for the ximian-setup-tools backends.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Arturo Espinosa <arturo@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/){
+
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/util.pl$DOTIN";
+require "$SCRIPTSDIR/file.pl$DOTIN";
+require "$SCRIPTSDIR/debug.pl$DOTIN";
+
+
+# The concept of keyword (kw) here is a key, normaly in its own line, whose
+# boolean representation is its own existence.
+
+# Every final parsing function to be used by a table must handle one key
+# at a time, but maybe parse several values from there and return a
+# ref to array or hash.
+#
+# Always return a scalar. If you need to return an array or a hash,
+# return a ref to it.
+
+# First some helper functions for the whole process.
+# Expand substrings of the form #$substr# to the $value in
+# the string or recursively in the array $strarr.
+
+sub gst_parse_expand
+{
+ my ($strarr, $substr, $value) = @_;
+
+ if (ref $strarr eq "ARRAY")
+ {
+ my ($i);
+
+ $strarr = [ @$strarr ];
+ foreach $i (@$strarr)
+ {
+ $i = &gst_parse_expand ($i, $substr, $value);
+ }
+
+ return $strarr;
+ }
+
+ $strarr =~ s/\#$substr\#/$value/;
+ return $strarr;
+}
+
+sub gst_parse_replace_hash_values
+{
+ my ($cp, $hash) = @_;
+ my ($j, $replace_key, $value);
+
+ foreach $j (@$cp)
+ {
+ while ($j =~ /%([^%]*)%/)
+ {
+ $replace_key = $1;
+ if (exists $$hash{$replace_key})
+ {
+ $value = $$hash{$replace_key};
+ if (ref $value)
+ {
+ $j = $value;
+ }
+ else
+ {
+ $j =~ s/%$replace_key%/$value/g;
+ }
+ }
+ else
+ {
+ &gst_debug_print_line ("Warning: gst_parse_replace_hash_values: key $replace_key doesn't exist.");
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+sub gst_parse_replace_files
+{
+ my ($values, $fn_hash) = @_;
+ my @ret;
+
+ return () if $values eq undef;
+ $values = [$values] if !ref $values;
+
+ foreach $i (@$values)
+ {
+ if (exists $$fn_hash{$i})
+ {
+ push @ret, $$fn_hash{$i};
+ }
+ else
+ {
+ push @ret, $i;
+ }
+ }
+
+ return @ret;
+}
+
+# Additional abstraction: parse table entries can have
+# arrays inside. The parsing proc will be ran with every
+# combination that the arrays provide. Ex:
+# ["user", \&gst_parse_foo, [0, 1], [2, 3] ] will parse
+# using the combinatory of [0, 1]x[2, 3] until a result
+# ne undef is given. Check RedHat 7.2's network parse table
+# for further enlightenment.
+sub gst_parse_run_entry
+{
+ my ($hash, $key, $proc, $cp) = @_;
+ my ($ncp, $i, $j, $res);
+
+ $ncp = [@$cp];
+ for ($i = 0; $i < scalar (@$cp); $i ++)
+ {
+ if (ref $$cp[$i] eq "ARRAY")
+ {
+ foreach $j (@{$$cp[$i]})
+ {
+ $$ncp[$i] = $j;
+ $res = &gst_parse_run_entry ($hash, $key, $proc, $ncp);
+ return $res if $res ne undef;
+ }
+ return undef;
+ }
+ }
+
+ # OK, the given entry didn't have any array refs in it...
+
+ return undef if (!&gst_parse_replace_hash_values ($cp, $hash));
+
+ &gst_report_enter ();
+ &gst_report ("parse_table", "$key");
+ &gst_report_leave ();
+
+ $$hash{$key} = &$proc (@$cp);
+ return $$hash{$key};
+}
+
+# OK, this is the good stuff:
+
+# gst_parse_from_table takes a file mapping and a parse table.
+#
+# The functions in the replace tables, most of which are coded in
+# this file, receive the mapped files of the first argument, and then
+# a set of values.
+
+# The value the parse function returns is set into a hash,
+# using as key the first item of the parse table entry. This is done
+# only if the $hash{$key} is empty, which allows us to try with
+# several parse methods to try to get a value, where our parse functions
+# can return undef if they failed to get the requested value.
+#
+# A ref to the hash with all the fetched values is returned.
+sub gst_parse_from_table
+{
+ my ($fn, $table) = @_;
+ my %hash;
+ my ($key, $proc, @param);
+ my ($i, @cp, @files);
+
+ foreach $i (@$table)
+ {
+ @cp = @$i;
+ $key = shift (@cp);
+
+ if ($hash{$key} eq undef)
+ {
+ $proc = shift (@cp);
+ @files = &gst_parse_replace_files (shift (@cp), $fn);
+
+ # Don't unshift the resulting files if none were given.
+ unshift @cp, @files if (scalar @files) > 0;
+
+ &gst_parse_run_entry (\%hash, $key, $proc, \@cp);
+ }
+ }
+
+ foreach $i (keys (%hash))
+ {
+ delete $hash{$i} if ($hash{$i} eq undef);
+ }
+
+ return \%hash;
+}
+
+# Just return the passed values. If there's just
+# one value, the value. If more, a reference to an
+# array with the values.
+sub gst_parse_trivial
+{
+ my (@res) = @_;
+
+ &gst_report_enter ();
+ &gst_report ("parse_trivial", "@res");
+ &gst_report_leave ();
+
+ return $res[0] if (scalar @res) <= 1;
+ return \@res;
+}
+
+# Try to read a line from $fd and remove any leading or
+# trailing white spaces. Return ref to read $line or
+# -1 if eof.
+sub gst_parse_chomp_line_std
+{
+ my ($fd) = @_;
+ my $line;
+
+ $line = <$fd>;
+ return -1 if !$line;
+
+ chomp $line;
+ $line =~ s/^[ \t]+//;
+ $line =~ s/[ \t]+$//;
+
+ return \$line;
+}
+
+# Assuming $line is a line read from a shell file,
+# remove comments.
+sub gst_parse_process_sh_line
+{
+ my ($line) = @_;
+ my ($pline);
+
+ # This will put escaped hashes out of danger.
+ # But only inside valid quotes!
+ while ($line =~ /([^\"\']*[\"\'][^\#\"\']*)(\#?)([^\"\']*[\"\'])/g)
+ {
+ $pline .= $1;
+ $pline .= "__hash__" if ($2 ne undef);
+ $pline .= $3;
+ }
+
+ # The line may not match the regexp above,
+ $pline = $line if ($pline eq undef);
+
+ $pline =~ s/\\\#/\\__hash__/g;
+
+ # Nuke everything after a hash and bye bye trailing spaces.
+ $pline =~ s/[ \t]*\#.*//;
+
+ # Let escaped hashes come back home.
+ $pline =~ s/__hash__/\#/g;
+
+ return $pline;
+}
+
+# Same as gst_parse_chomp_line_std, but apply
+# the sh line processing before returning.
+# -1 if eof, ref to read $line if success.
+sub gst_parse_chomp_line_hash_comment
+{
+ my ($fd) = @_;
+ my $line;
+
+ $line = &gst_parse_chomp_line_std ($fd);
+ return -1 if $line == -1;
+
+ $line = &gst_parse_process_sh_line ($$line);
+ return \$line;
+}
+
+# Get an sh line, and remove the export keyword, if any.
+sub gst_parse_chomp_line_sh_export
+{
+ my ($fd) = @_;
+ my $line;
+
+ $line = &gst_parse_chomp_line_hash_comment ($fd);
+ return -1 if $line == -1;
+
+ $line = $$line;
+
+ $line =~ s/^export //;
+
+ return \$line;
+}
+
+# Parse a $file, wich is assumed to have a column-based format, with $re matching field separators
+# and one record per line. Search for $key, and return either a scalar with the first ocurrence,
+# or an array with all the found ocurrences.
+sub gst_parse_split_ref
+{
+ my ($file, $key, $re, $all, $line_read_proc) = @_;
+ my ($fd, @line, @res);
+
+ &gst_report_enter ();
+ &gst_report ("parse_split", $key, $file);
+
+ $proc = $line_read_proc? $line_read_proc : \&gst_parse_chomp_line_std;
+
+ $fd = &gst_file_open_read_from_names ($file);
+ $all = 0 if !$fd;
+
+ while (($line = &$proc ($fd)) != -1)
+ {
+ $line = $$line;
+ next if $line eq "";
+
+ @line = split ($re, $line, 2);
+
+ if (shift (@line) =~ "^$key\$")
+ {
+ if ($all) {
+ push @res, $line[0];
+ }
+ else
+ {
+ &gst_report_leave ();
+ &gst_file_close ($fd);
+ return \$line[0];
+ }
+ }
+ }
+
+ &gst_report_leave ();
+ &gst_file_close ($fd);
+ return \@res if ($all);
+ return -1;
+}
+
+sub gst_parse_split
+{
+ my $res;
+
+ # Don't pass @_ like this anywhere. This is bad practice.
+ $res = &gst_parse_split_ref (@_);
+
+ return $$res if ref $res eq "SCALAR";
+ return @$res if ref $res eq "ARRAY";
+ return undef;
+}
+
+# This gives meaning to the $all flag of gst_parse_split, and returns a reference to the array, which
+# is what we want. (ie search a.com\nsearch b.com\nsearch c.com)
+sub gst_parse_split_all
+{
+ my ($file, $key, $re, $line_read_proc) = @_;
+ my @a;
+
+ @a = &gst_parse_split ($file, $key, $re, 1, $line_read_proc);
+
+ return \@a;
+}
+
+# Same, but use the hash_comment routine for line analysis.
+sub gst_parse_split_all_hash_comment
+{
+ my ($file, $key, $re) = @_;
+
+ return &gst_parse_split_all ($file, $key, $re, \&gst_parse_chomp_line_hash_comment);
+}
+
+# Make the elements of the resulting array unique.
+sub gst_parse_split_all_unique_hash_comment
+{
+ my ($file, $key, $re) = @_;
+ my ($arr, @res);
+ my (%hash, $i);
+
+ $arr = &gst_parse_split_all ($file, $key, $re, \&gst_parse_chomp_line_hash_comment);
+
+ foreach $i (@$arr)
+ {
+ next if exists $hash{$i};
+ $hash{$i} = 1;
+ push @res, $i;
+ }
+
+ return \@res;
+}
+
+sub gst_parse_split_all_array_with_pos
+{
+ my ($file, $key, $pos, $re, $sep, $line_read_proc) = @_;
+ my ($arr, @s, @ret, $i);
+
+ $arr = &gst_parse_split_all ($file, $key, $re, $line_read_proc);
+
+ foreach $i (@$arr)
+ {
+ @s = split ($sep, $i);
+ push @ret, @s[0];
+ }
+
+ return \@ret;
+}
+
+# Same, but for $all = 0. (ie nameserver 10.0.0.1)
+sub gst_parse_split_first_str
+{
+ my ($file, $key, $re, $line_read_proc) = @_;
+
+ return &gst_parse_split ($file, $key, $re, 0, $line_read_proc);
+}
+
+# Interpret the result as a boolean. (ie multi on)
+sub gst_parse_split_first_bool
+{
+ my ($file, $key, $re, $line_read_proc) = @_;
+ my $ret;
+
+ $ret = &gst_parse_split_first_str ($file, $key, $re, $line_read_proc);
+
+ return undef if ($ret eq undef);
+ return (&gst_util_read_boolean ($ret)? 1: 0);
+}
+
+# After getting the first field, split the result with $sep matching separators. (ie order hosts,bind)
+sub gst_parse_split_first_array
+{
+ my ($file, $key, $re, $sep, $line_read_proc) = @_;
+ my @ret;
+
+ @ret = split ($sep, &gst_parse_split ($file, $key, $re, 0, $line_read_proc));
+
+ return \@ret;
+}
+
+sub gst_parse_split_first_array_pos
+{
+ my ($file, $key, $pos, $re, $sep, $line_read_proc) = @_;
+ my (@ret);
+
+ @ret = split ($sep, &gst_parse_split ($file, $key, $re, 0, $line_read_proc));
+ return $ret[$pos];
+}
+
+# Do an gst_parse_split_first_array and then make
+# the array elements unique. This is to fix broken
+# searchdomain entries in /etc/resolv.conf, for example.
+sub gst_parse_split_first_array_unique
+{
+ my ($file, $key, $re, $sep, $line_read_proc) = @_;
+ my (@arr, @res);
+ my (%hash, $i);
+
+ @arr = split ($sep, &gst_parse_split ($file, $key, $re, 0, $line_read_proc));
+
+ foreach $i (@arr)
+ {
+ next if exists $hash{$i};
+ $hash{$i} = 1;
+ push @res, $i;
+ }
+
+ return \@res;
+}
+
+# For all keys in $file, sepparated from its values
+# by $key_re, sepparate its values using $value_re
+# and assign to a newly created hash. Use ONLY when
+# you don't know what keys you are going to parse
+# (i.e. /etc/hosts). Any other application will not
+# be very portable and should be avoided.
+sub gst_parse_split_hash
+{
+ my ($file, $key_re, $value_re) = @_;
+ my ($fd, @line, %res, $key);
+
+ &gst_report_enter ();
+ &gst_report ("parse_split_hash", $file);
+
+ $fd = &gst_file_open_read_from_names ($file);
+
+ while (<$fd>)
+ {
+ chomp;
+ s/^[ \t]+//;
+ s/[ \t]+$//;
+ s/\#.*$//;
+ next if (/^$/);
+ @line = split ($key_re, $_, 2);
+
+ $key = shift (@line);
+ push @{$res{$key}}, split ($value_re, $line[0]);
+ }
+
+ &gst_file_close ($fd);
+ &gst_report_leave ();
+ return undef if (scalar keys (%res) == 0);
+ return \%res;
+}
+
+# Same as above, but join lines that end with '\'.
+sub gst_parse_split_hash_with_continuation
+{
+ my ($file, $key_re, $value_re) = @_;
+ my ($fd, $l, @line, %res, $key);
+
+ &gst_report_enter ();
+ &gst_report ("parse_split_hash_cont", $file);
+
+ $fd = &gst_file_open_read_from_names ($file);
+
+ while (($l = &gst_parse_ini_line_read ($fd)) != -1)
+ {
+ $_ = $$l;
+ chomp;
+ s/^[ \t]+//;
+ s/[ \t]+$//;
+ s/\#.*$//;
+ next if (/^$/);
+ @line = split ($key_re, $_, 2);
+
+ $key = shift (@line);
+ $res{$key} = [ split ($value_re, $line[0]) ];
+ }
+
+ &gst_file_close ($fd);
+ &gst_report_leave ();
+ return undef if (scalar keys (%res) == 0);
+ return \%res;
+}
+
+# Remove escape sequences in a shell value.
+sub gst_parse_shell_unescape
+{
+ my $ret = $_[0];
+
+ # Quote shell special chars.
+ $ret =~ s/\\\"/\\_/g;
+ $ret =~ s/\"//g;
+ $ret =~ s/\\_/\"/g;
+ $ret =~ s/\\\'/\\_/g;
+ $ret =~ s/\'//g;
+ $ret =~ s/\\_/\'/g;
+ $ret =~ s/\\(.)/$1/g;
+
+ return $ret;
+}
+
+# unescape (escape (x)) == x
+sub gst_parse_shell_escape
+{
+ my ($value) = @_;
+
+ $value =~ s/([\"\`\$\\])/\\$1/g;
+ $value = "\"$value\"" if ($value =~ /[ \t\'&|*?\[\]\{\}\{\}<>]/);
+
+ return $value;
+}
+
+# For files which are a list of /bin/sh shell variable declarations. (ie GATEWAY=10.10.10.1)
+sub gst_parse_sh
+{
+ my ($file, $key) = @_;
+ my $ret;
+
+ &gst_report_enter ();
+ &gst_report ("parse_sh", $key, $file);
+ $ret = &gst_parse_split_first_str ($file, $key, "[ \t]*=[ \t]*",
+ \&gst_parse_chomp_line_hash_comment);
+ &gst_report_leave ();
+
+ return &gst_parse_shell_unescape ($ret);
+}
+
+# Same, but interpret the returning value as a bool. (ie NETWORKING=yes)
+sub gst_parse_sh_bool
+{
+ my ($file, $key) = @_;
+ my $ret;
+
+ $ret = &gst_parse_sh ($file, $key);
+
+ return undef if ($ret eq undef);
+ return (&gst_util_read_boolean ($ret)? 1: 0);
+}
+
+# Get an sh value and then split with $re, returning ref to resulting array.
+sub gst_parse_sh_split
+{
+ my ($file, $key, $re) = @_;
+ my (@ret, $val);
+
+ $val = &gst_parse_sh ($file, $key);
+ @ret = split ($re, $val);
+
+ return \@ret;
+}
+
+# Get a fully qualified hostname from a $key shell var in $file
+# and extract the hostname from there. e.g.: suse70's /etc/rc.config's FQHOSTNAME.
+sub gst_parse_sh_get_hostname
+{
+ my ($file, $key) = @_;
+ my ($val);
+
+ $val = &gst_parse_sh_split ($file, $key, "\\.");
+
+ return $$val[0];
+}
+
+# Get a fully qualified hostname from a $key shell var in $file
+# and extract the domain from there. e.g.: suse70's /etc/rc.config's FQHOSTNAME.
+sub gst_parse_sh_get_domain
+{
+ my ($file, $key) = @_;
+ my ($val);
+
+ $val = &gst_parse_sh_split ($file, $key, "\\.");
+
+ return join ".", @$val[1..$#$val];
+}
+
+# For files which are a list of /bin/sh shell variable exports. (eg export GATEWAY=10.10.10.1)
+sub gst_parse_sh_export
+{
+ my ($file, $key) = @_;
+ my $ret;
+
+ &gst_report_enter ();
+ &gst_report ("parse_sh", $key, $file);
+ $ret = &gst_parse_split_first_str ($file, $key, "[ \t]*=[ \t]*",
+ \&gst_parse_chomp_line_sh_export);
+ &gst_report_leave ();
+
+ return &gst_parse_shell_unescape ($ret);
+}
+
+# Same, but interpret the returing value as a bool. (ie export NETWORKING=yes)
+sub gst_parse_sh_export_bool
+{
+ my ($file, $key) = @_;
+ my $ret;
+
+ $ret = &gst_parse_sh_export ($file, $key);
+
+ return undef if ($ret eq undef);
+ return (&gst_util_read_boolean ($ret)? 1: 0);
+}
+
+# Same, but accepting a regexp and returning the value between the paren operator
+sub gst_parse_sh_re
+{
+ my ($file, $key, $re) = @_;
+ my $ret;
+
+ $ret = &gst_parse_sh ($file, $key);
+
+ $ret =~ /$re/i;
+ return $1;
+}
+
+
+# Search for $keyword in $file, delimited by $re (default " ") or EOL.
+# If keyword exists, return 1, else 0.
+sub gst_parse_kw
+{
+ my ($file, $keyword, $re, $line_read_proc) = @_;
+ my $res;
+
+ &gst_report_enter ();
+ &gst_report ("parse_kw", $keyword, $file);
+
+ if (! -f "$gst_prefix/$file")
+ {
+ &gst_report_enter ();
+ &gst_report ("file_open_read_failed", $file);
+ &gst_report_leave ();
+ &gst_report_leave ();
+ return undef;
+ }
+
+ $re = " " if $re eq undef;
+ $res = &gst_parse_split_ref ($file, $keyword, $re, 0, $line_read_proc);
+
+ &gst_report_leave ();
+ return 0 if $res == -1;
+ return 1;
+}
+
+# A file containing the desired value in its first line. (ie /etc/hostname)
+sub gst_parse_line_first
+{
+ my ($file) = @_;
+ my ($fd, $res);
+
+ &gst_report_enter ();
+ &gst_report ("parse_line_first", $file);
+ $fd = &gst_file_open_read_from_names ($file);
+ &gst_report_leave ();
+
+ return undef if !$fd;
+
+ chomp ($res = <$fd>);
+ &gst_file_close ($fd);
+ return $res;
+}
+
+# parse a chat file, searching for an entry that matches $re.
+# $re must have one paren operator (ie "^atd[^0-9]*([0-9, -]+)").
+sub gst_parse_chat
+{
+ my ($file, $re) = @_;
+ my ($fd, $found);
+
+ &gst_report_enter ();
+ &gst_report ("parse_chat", $file);
+ $fd = &gst_file_open_read_from_names ("$file");
+ &gst_report_leave ();
+ return undef if !$fd;
+
+ while (<$fd>)
+ {
+ # We'll be emptying $_ as we "scan".
+ chomp;
+ while ($_ ne "")
+ {
+ # If it uses quotes. FIXME: Assuming they surround the whole string.
+ if (/^\'/)
+ {
+ s/\'([^\']*)\' ?//;
+ $found = $1;
+ }
+ else
+ {
+ s/([^ \t]*) ?//;
+ $found = $1;
+ }
+
+ # If it looks like what we're looking for, return what matched the parens.
+ if ($found =~ /$re/i)
+ {
+ &gst_file_close ($fd);
+ return $1;
+ }
+ }
+ }
+
+ &gst_file_close ($fd);
+ # Oops: not found.
+ return undef;
+}
+
+# Clean an ini line of comments and leading or
+# trailing spaces.
+sub gst_parse_ini_line_clean
+{
+ $_ = $_[0];
+
+ chomp;
+ s/\#.*//;
+ s/;.*//;
+ s/^[ \t]+//;
+ s/[ \t]+$//;
+
+ return $_;
+}
+
+# Read an ini line, which may have to be joined
+# with the next one if it ends with '\'.
+sub gst_parse_ini_line_read
+{
+ my $fd = $_[0];
+ my $l;
+
+ $l = <$fd>;
+ return -1 if ($l eq undef);
+
+ $l = &gst_parse_ini_line_clean ($l);
+ while ($l =~ /\\$/)
+ {
+ $l =~ s/\\$//;
+ $l .= &gst_parse_ini_line_clean (scalar <$fd>);
+ }
+
+ return \$l;
+}
+
+# Return an array of all found sections in $file.
+sub gst_parse_ini_sections
+{
+ my ($file) = @_;
+ my (@sections, $line);
+
+ $fd = &gst_file_open_read_from_names ($file);
+
+ while (($line = &gst_parse_ini_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if (/^$/);
+ push @sections, $1 if (/\[([^\]]+)\]/i);
+ }
+
+ &gst_file_close ($fd);
+
+ return @sections;
+}
+
+# Get the value of a $var in a $section from $file.
+sub gst_parse_ini
+{
+ my ($file, $section, $var) = @_;
+ my ($fd, $res, $line);
+ my $found_section_flag = 0;
+
+ &gst_report_enter ();
+ &gst_report ("parse_ini", $var, $file, $section);
+ $fd = &gst_file_open_read_from_names ($file);
+ &gst_report_leave ();
+ $res = undef;
+
+ while (($line = &gst_parse_ini_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if (/^$/);
+
+ if (/\[$section\]/i)
+ {
+ $found_section_flag = 1;
+ next;
+ }
+
+ if ($found_section_flag)
+ {
+ if (/^$var[ \t]*=/i)
+ {
+ s/^$var[ \t]*=[ \t]*//i;
+ $res = $_;
+ last;
+ }
+ elsif (/\[\S+\]/i)
+ {
+ last;
+ }
+ }
+ }
+
+ &gst_file_close ($fd);
+
+ return $res;
+}
+
+# Same, but treat value as bool and return 1/0.
+sub gst_parse_ini_bool
+{
+ my ($file, $section, $var) = @_;
+ my $ret;
+
+ $ret = &gst_parse_ini ($file, $section, $var);
+
+ return undef if ($ret eq undef);
+ return (&gst_util_read_boolean ($ret)? 1: 0);
+}
+
+sub gst_parse_cap_line_clean
+{
+ $_ = $_[0];
+
+ chomp;
+ s/^[ \t]*\#.*//;
+ s/;.*//;
+ s/^[ \t]+//;
+ s/[ \t]+$//;
+
+ return $_;
+}
+
+sub gst_parse_cap_line_read
+{
+ my $fd = $_[0];
+ my $l;
+
+ $l = <$fd>;
+ return -1 if ($l eq undef);
+
+ $l = &gst_parse_cap_line_clean ($l);
+ while ($l =~ /\\$/)
+ {
+ $l =~ s/\\$//;
+ $l .= &gst_parse_cap_line_clean (scalar <$fd>);
+ }
+
+ return \$l;
+}
+
+sub gst_parse_cap_sections
+{
+ my ($file) = @_;
+ my (@sections, $line);
+
+ $fd = &gst_file_open_read_from_names ($file);
+
+ while (($line = &gst_parse_cap_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if (/^$/);
+ push @sections, $1 if (/^([^:|]+)/i);
+ }
+
+ &gst_file_close ($fd);
+ return @sections;
+}
+
+sub gst_parse_cap
+{
+ my ($file, $section, $var) = @_;
+ my ($fd, $res, $line);
+ my $found_section_flag = 0;
+
+ $fd = &gst_file_open_read_from_names ($file);
+ $res = undef;
+
+ while (($line = &gst_parse_ini_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if (/^$/);
+ if (/^$section[:|]/i)
+ {
+ $found_section_flag = 1;
+ }
+
+ if ($found_section_flag && /:$var\#/i)
+ {
+ $_ =~ /:$var\#([^:]*)/;
+ $res = $1;
+ last;
+ }
+# if ($found_section_flag && /:$var[#=]/i)
+# {
+# $_ =~ /:$var[#=]([^:]*)/;
+# $res = $1;
+# last;
+# }
+ }
+
+ &gst_file_close ($fd);
+ return $res;
+}
+
+sub gst_parse_cap_bool
+{
+ my ($file, $section, $var) = @_;
+ my ($fd, $res, $line);
+ my $found_section_flag = 0;
+
+ $fd = &gst_file_open_read_from_names ($file);
+ $res = 0;
+
+ while (($line = &gst_parse_ini_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if (/^$/);
+ if (/^$section[:|]/i)
+ {
+ $found_section_flag = 1;
+ }
+
+ if ($found_section_flag && /:$var[:\#=]/i)
+ {
+ $res = 1;
+ last;
+ }
+ }
+
+ &gst_file_close ($fd);
+ return $res;
+}
+
+# Load a printcap file to buffer, join \ lines and split them back up into a
+# 'one option, printtool comment or section name per line' format.
+sub gst_parse_printcap_buffer_load
+{
+ my ($file) = @_;
+ my ($inbuf, @outbuf);
+
+ $inbuf = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($inbuf);
+
+ for $i (@$inbuf)
+ {
+ my ($comment) = ("");
+
+ chomp $i;
+ $comment = $1 if $i =~ s/^([ \t]*[\#].*)//;
+
+ if ($i ne "")
+ {
+ my @line = split /:/, $i;
+
+ if ($i =~ /^[a-z0-9]+/i)
+ {
+ push @outbuf, ($line [0] . ":\n");
+ shift @line;
+ }
+
+ for $elem (@line)
+ {
+ $elem =~ s/^[ \t]//;
+ $elem =~ s/[ \t]$//;
+ if ($elem ne "")
+ {
+ push @outbuf, ("\t:$elem:\n");
+ }
+ }
+ }
+ elsif ($comment ne "")
+ {
+ push @outbuf, ($comment . "\n");
+ }
+ else
+ {
+ push @outbuf, "\n";
+ }
+ }
+
+ return \@outbuf;
+}
+
+# Find next printer definition, returning (printtool-comment-lineno, stanza-name-lineno).
+sub gst_parse_printcap_get_next_stanza
+{
+ my ($buf, $line_no) = @_;
+ my ($last_printtool_line) = (-1);
+
+ while ($line_no <= $#$buf)
+ {
+ if ($$buf [$line_no] =~ /^\#\#PRINTTOOL3\#\#/)
+ {
+ $last_printtool_line = $line_no;
+ }
+ elsif ($$buf [$line_no] =~ /^[a-z0-9]+/i)
+ {
+ return ($last_printtool_line, $line_no);
+ }
+
+ $line_no++;
+ }
+
+ return (-1, -1);
+}
+
+# Find next printer option.
+sub gst_parse_printcap_get_next_option
+{
+ my ($buf, $line_no) = @_;
+
+ while ($line_no <= $#$buf)
+ {
+ if ($$buf [$line_no] =~ /^\#\#PRINTTOOL3\#\#/ ||
+ $$buf [$line_no] =~ /^[a-z0-9]+/i)
+ {
+ last;
+ }
+
+ if ($$buf [$line_no] =~ /^\t:/)
+ {
+ return $line_no;
+ }
+
+ $line_no++;
+ }
+
+ return -1;
+}
+
+sub gst_parse_printcap_parse_stanza
+{
+ my ($stanza) = @_;
+ my ($key);
+
+ $key = $1 if $stanza =~ /^([a-z0-9]+)/i;
+ return $key;
+}
+
+sub gst_parse_printcap_parse_option
+{
+ my ($option) = @_;
+ my ($key, $value);
+
+ $key = $1 if $option =~ /^\t:([a-z0-9]+)/i;
+ $value = $1 if $option =~ /^\t:[a-z0-9]+[\#=]([a-z0-9\/_-]*)/i;
+ return ($key, $value);
+}
+
+# Locate stanza line for $printer in $buf, starting at $line_no.
+sub gst_parse_printcap_find_stanza
+{
+ my ($buf, $line_no, $printer) = @_;
+ my ($printtool_line_no, $found_printer);
+
+ while ((($printtool_line_no, $line_no) = &gst_parse_printcap_get_next_stanza ($buf, $line_no)))
+ {
+ if ($line_no == -1) { last; }
+
+ $found_printer = &gst_parse_printcap_parse_stanza ($$buf [$line_no]);
+ return ($printtool_line_no, $line_no) if ($found_printer eq $printer);
+ $line_no++;
+ }
+
+ return (-1, -1);
+}
+
+# Search buffer for option with key $key, starting
+# at $line_no position. Return line number, or -1 if not found.
+sub gst_parse_printcap_find_option
+{
+ my ($buf, $line_no, $key) = @_;
+ my $found_key;
+
+ while (($line_no = &gst_parse_printcap_get_next_option ($buf, $line_no)) != -1)
+ {
+ ($found_key) = &gst_parse_printcap_parse_option ($$buf [$line_no]);
+ return $line_no if ($found_key eq $key);
+ $line_no++;
+ }
+
+ return -1;
+}
+
+# High-level API.
+sub gst_parse_printcap
+{
+ my ($file, $section, $var) = @_;
+ my ($printtool_line_no, $stanza_line_no, $option_line_no);
+ my ($buf);
+ my ($key, $value);
+
+ $buf = &gst_parse_printcap_buffer_load ($file);
+
+ ($printtool_line_no, $stanza_line_no) = &gst_parse_printcap_find_stanza ($buf, 0, $section);
+ return undef if ($stanza_line_no == -1);
+
+ $option_line_no = &gst_parse_printcap_find_option ($buf, $stanza_line_no + 1, $var);
+ return undef if ($option_line_no == -1);
+
+ ($key, $value) = &gst_parse_printcap_parse_option ($$buf [$option_line_no]);
+ return $value;
+}
+
+# High-level API.
+sub gst_parse_printcap_bool
+{
+ my ($file, $section, $var) = @_;
+ my ($printtool_line_no, $stanza_line_no, $option_line_no);
+ my ($buf);
+ my ($key, $value);
+
+ $buf = &gst_parse_printcap_buffer_load ($file);
+
+ ($printtool_line_no, $stanza_line_no) = &gst_parse_printcap_find_stanza ($buf, 0, $section);
+ return 0 if ($stanza_line_no == -1);
+
+ $option_line_no = &gst_parse_printcap_find_option ($buf, $stanza_line_no + 1, $var);
+ return 0 if ($option_line_no == -1);
+
+ return 1;
+}
+
+# Debian interfaces(5) states that files starting with # are comments.
+# Also, leading and trailing spaces are ignored.
+sub gst_parse_interfaces_line_clean
+{
+ $_ = $_[0];
+
+ chomp;
+ s/^[ \t]+//;
+ s/^\#.*//;
+ s/[ \t]+$//;
+
+ return $_;
+}
+
+# interfaces(5) also states that \ line continuation is possible.
+sub gst_parse_interfaces_line_read
+{
+ my $fd = $_[0];
+ my $l;
+
+ $l = <$fd>;
+ return -1 if ($l eq undef);
+
+ $l = &gst_parse_interfaces_line_clean ($l);
+ while ($l =~ /\\$/)
+ {
+ $l =~ s/\\$//;
+ $l .= &gst_parse_interfaces_line_clean (scalar <$fd>);
+ }
+
+ return \$l;
+}
+
+# Read lines until a stanza, a line starting with $stanza_type is found.
+# Return ref to an array with the stanza params split.
+sub gst_parse_interfaces_get_next_stanza
+{
+ my ($fd, $stanza_type) = @_;
+ my $line;
+
+ while (($line = &gst_parse_interfaces_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ if (/^$stanza_type[ \t]+[^ \t]/)
+ {
+ s/^$stanza_type[ \t]+//;
+ return [ split ("[ \t]+", $_) ];
+ }
+ }
+
+ return -1;
+}
+
+# Read lines until a line not recognized as a stanza is
+# found, and split in a "tuple" of key/value.
+sub gst_parse_interfaces_get_next_option
+{
+ my $fd = $_[0];
+ my $line;
+
+ while (($line = &gst_parse_interfaces_line_read ($fd)) != -1)
+ {
+ $_ = $$line;
+ next if /^$/;
+
+ return [ split ("[ \t]+", $_, 2) ] if (!/^iface[ \t]/);
+ return -1;
+ }
+
+ return -1;
+}
+
+# Get all stanzas from file. Return array.
+sub gst_parse_interfaces_stanzas
+{
+ my ($file, $stanza_type) = @_;
+ my ($fd, @res);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ $res = undef;
+
+ while (($_ = &gst_parse_interfaces_get_next_stanza ($fd, $stanza_type)) != -1)
+ {
+ push @res, $_;
+ }
+
+ &gst_file_close ($fd);
+
+ return @res;
+}
+
+# Find stanza for $iface in $file, and return
+# tuple for option with $key. Return -1 if unexisting.
+sub gst_parse_interfaces_option_tuple
+{
+ my ($file, $iface, $key, $all) = @_;
+ my ($fd, @res);
+
+ $fd = &gst_file_open_read_from_names ($file);
+
+ while (($stanza = &gst_parse_interfaces_get_next_stanza ($fd, "iface")) != -1)
+ {
+ if ($$stanza[0] eq $iface)
+ {
+ while (($tuple = &gst_parse_interfaces_get_next_option ($fd)) != -1)
+ {
+ if ($$tuple[0] =~ /$key/)
+ {
+ return $tuple if !$all;
+ push @res, $tuple;
+ }
+ }
+
+ return -1 if !$all;
+ }
+ }
+
+ return @res if $all;
+ return -1;
+}
+
+# Go get option $kw for $iface stanza. If found,
+# return 1 (true), else, false.
+sub gst_parse_interfaces_option_kw
+{
+ my ($file, $iface, $kw) = @_;
+ my $tuple;
+
+ &gst_report_enter ();
+ &gst_report ("parse_ifaces_kw", $kw, $file);
+ $tuple = &gst_parse_interfaces_option_tuple ($file, $iface, $kw);
+ &gst_report_leave ();
+
+ if ($tuple != -1)
+ {
+ &gst_report ("parse_ifaces_kw_strange", $iface, $file) if ($$tuple[1] ne "");
+
+ return 1;
+ }
+
+ return 0;
+}
+
+# For such keywords as noauto, whose existence means
+# a false value.
+sub gst_parse_interfaces_option_kw_not
+{
+ my ($file, $iface, $kw) = @_;
+
+ return &gst_parse_interfaces_option_kw ($file, $iface, $kw)? 0 : 1;
+}
+
+# Go get option $key for $iface in $file and return value.
+sub gst_parse_interfaces_option_str
+{
+ my ($file, $iface, $key) = @_;
+ my $tuple;
+
+ &gst_report_enter ();
+ &gst_report ("parse_ifaces_str", $kw, $file);
+ $tuple = &gst_parse_interfaces_option_tuple ($file, $iface, $key);
+ &gst_report_leave ();
+
+ if ($tuple != -1)
+ {
+ return $$tuple[1];
+ }
+
+ return undef;
+}
+
+
+# Implementing pump(8) pump.conf file format parser.
+# May be useful for dhcpd too.
+sub gst_parse_pump_get_next_option
+{
+ my ($fd) = @_;
+ my $line;
+
+ while (($line = &gst_parse_interfaces_line_read ($fd)) != -1)
+ {
+ $line = $$line;
+ if ($line ne "")
+ {
+ return [ split ("[ \t]+", $line, 2) ];
+ }
+ }
+
+ return -1;
+}
+
+sub gst_parse_pump_get_device
+{
+ my ($fd, $iface) = @_;
+ my ($opt);
+
+ while (($opt = &gst_parse_pump_get_next_option ($fd)) != -1)
+ {
+ if ($$opt[0] eq "device")
+ {
+ $$opt[1] =~ s/[ \t]*\{//;
+ return 1 if $$opt[1] eq $iface;
+ }
+ }
+
+ return 0;
+}
+
+sub gst_parse_pump_get_iface_option_ref
+{
+ my ($file, $iface, $key) = @_;
+ my ($fd, $opt, $ret);
+
+ $fd = &gst_file_open_read_from_names ($file);
+
+ if (&gst_parse_pump_get_device ($fd, $iface))
+ {
+ while (($opt = &gst_parse_pump_get_next_option ($fd)) != -1)
+ {
+ if ($$opt[0] eq $key)
+ {
+ $ret = &gst_parse_shell_unescape ($$opt[1]);
+ return \$ret;
+ }
+
+ return -1 if ($$opt[0] eq "}");
+ }
+ }
+
+ return -1;
+}
+
+sub gst_parse_pump_get_iface_kw
+{
+ my ($file, $iface, $key) = @_;
+ my ($ret);
+
+ return 1 if &gst_parse_pump_get_iface_option_ref ($file, $iface, $key) != -1;
+ return 0;
+}
+
+sub gst_parse_pump_get_iface_kw_not
+{
+ my ($file, $iface, $key) = @_;
+
+ return 0 if &gst_parse_pump_get_iface_option_ref ($file, $iface, $key) != -1;
+ return 1;
+}
+
+# Read a variable out of an XML document. The varpath is the '/'-separated path to the
+# XML tag. If the name of a property is passed, that property of the leaf tag is read,
+# otherwise the tag's PCDATA.
+sub gst_parse_xml
+{
+ my ($file, $varpath, $property) = @_;
+ my ($model, $branch);
+
+ ($model) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_find ($model, $varpath);
+
+ if ($branch)
+ {
+ return &gst_xml_model_get_attribute ($branch, $property) if $property ne "";
+ return &gst_xml_model_get_pcdata ($branch);
+ }
+
+ return undef;
+}
+
+sub gst_parse_xml_child_names
+{
+ my ($file, $varpath) = @_;
+ my ($model, $branch, @children);
+
+ ($model) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_find ($model, $varpath);
+
+ if (!$branch) { return @children; }
+
+ my @list = @$branch;
+ shift @list; # Attributes
+
+ while (@list)
+ {
+ if ($list [0] ne "__unparsed__" && $list [0] ne "0")
+ {
+ push @children, shift @list;
+ }
+ else
+ {
+ shift @list;
+ }
+
+ shift @list;
+ }
+
+ return @children;
+}
+
+sub gst_parse_alchemist
+{
+ my ($file, $varpath) = @_;
+
+ $varpath = "/adm_context/datatree/" . $varpath;
+ return &gst_parse_xml ($file, $varpath, "VALUE");
+}
+
+sub gst_parse_alchemist_print
+{
+ my ($file, $printer, $varpath) = @_;
+
+ $varpath = "printconf/print_queues/" . $printer . "/" . $varpath;
+ return &gst_parse_alchemist ($file, $varpath);
+}
+
+sub gst_parse_alchemist_print_option
+{
+ my ($file, $printer, $name) = @_;
+ my ($varpath, $model, $branch, $fd, $options, $option);
+
+ ($model) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_find ($model, "/adm_context/datatree/printconf/print_queues/" . $printer .
+ "/filter_data/foomatic_defaults");
+
+ return undef if (!$branch);
+
+ $options = &gst_xml_model_get_children ($branch);
+
+ foreach $o (@$options)
+ {
+ my $opt_node = &gst_xml_model_find ($o, "name");
+ next if (!$opt_node);
+
+ if (&gst_xml_model_get_attribute ($opt_node, "VALUE") eq $name)
+ {
+ $option = $o;
+ last;
+ }
+ }
+
+ return undef if (!$option);
+
+ my $node = &gst_xml_model_find ($option, "default");
+ return undef if (!$node);
+
+ return &gst_xml_model_get_attribute ($node, "VALUE");
+}
+
+# extracts hostname from a fully qualified hostname
+# contained in a file
+sub gst_parse_fq_hostname
+{
+ my ($file) = @_;
+ my ($ret);
+
+ $ret = &gst_parse_line_first ($file);
+ $ret =~ s/\..*//; #remove domain
+
+ return $ret;
+}
+
+# extracts domain from a fully qualified hostname
+# contained in a file
+sub gst_parse_fq_domain
+{
+ my ($file) = @_;
+ my ($ret);
+
+ $ret = &gst_parse_line_first ($file);
+ $ret =~ s/^[^\.]*\.//;
+
+ return $ret;
+}
+
+sub gst_parse_rcinet1conf
+{
+ my ($file, $iface, $kw) = @_;
+ my ($line);
+
+ $iface =~ s/eth//;
+
+ #we must double escape those []
+ $line = "$kw\\[$iface\\]";
+
+ return &gst_parse_sh ($file, $line);
+}
+
+sub gst_parse_rcinet1conf_bool
+{
+ my ($file, $iface, $kw) = @_;
+ my ($ret);
+
+ $ret = &gst_parse_rcinet1conf ($file, $iface, $kw);
+
+ return undef if ($ret eq undef);
+ return (&gst_util_read_boolean ($ret)? 1: 0);
+}
+
+sub gst_parse_wireless_opts
+{
+ my ($file, $iface, $proc, $kw) = @_;
+ my $ifaces = &$proc ();
+ my $found = 0;
+ my $search = 1;
+ my $val = "";
+ my $fd;
+
+ foreach $i (@$ifaces)
+ {
+ $found = 1 if ($iface eq $i);
+ }
+
+ return undef if (!$found);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ while (<$fd>)
+ {
+ $line = $_;
+
+ if ($line =~ /^case/)
+ {
+ # we don't want to search inside the case
+ $search = 0;
+ }
+ elsif ($line =~ /^esac/)
+ {
+ # continue searching
+ $search = 1;
+ }
+ elsif (($line =~ /^[ \t]*$kw/ ) && ($search))
+ {
+ $line =~ s/.*=//;
+
+ if ($line =~ /"(.*)"/)
+ {
+ $line = $1;
+ }
+
+ $val = $line;
+ }
+ }
+
+ &gst_file_close ($fd);
+ return $val;
+}
+
+# function for parsing /etc/start_if.$iface files in FreeBSD
+sub gst_parse_startif
+{
+ my ($file, $regex) = @_;
+ my ($fd, $line, $val);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ $val = undef;
+
+ return undef if ($fd eq undef);
+
+ while (<$fd>)
+ {
+ chomp;
+
+ # ignore comments
+ next if (/^\#/);
+
+ if (/$regex/)
+ {
+ $val = $1;
+ }
+ }
+
+ # remove double quote
+ if ($val =~ /\"(.*)\"/)
+ {
+ $val = $1;
+ }
+
+ return $val;
+}
+
+# functions for parsing /etc/ppp/ppp.conf sections in FreeBSD
+sub gst_parse_pppconf_find_next_stanza
+{
+ my ($buff, $line_no) = @_;
+
+ $line_no = 0 if ($line_no eq undef);
+
+ while ($$buff[$line_no] ne undef)
+ {
+ if ($$buff[$line_no] !~ /^[\#\n]/)
+ {
+ return $line_no if ($$buff[$line_no] =~ /^[^ \t]+/);
+ }
+
+ $line_no++;
+ }
+
+ return -1;
+}
+
+sub gst_parse_pppconf_find_stanza
+{
+ my ($buff, $section) = @_;
+ my ($line_no) = 0;
+
+ while (($line_no = &gst_parse_pppconf_find_next_stanza ($buff, $line_no)) != -1)
+ {
+ return $line_no if ($$buff[$line_no] =~ /^$section\:/);
+ $line_no++;
+ }
+
+ return -1;
+}
+
+sub gst_parse_pppconf_common
+{
+ my ($file, $section, $key) = @_;
+ my ($fd, $val);
+
+ $fd = &gst_file_open_read_from_names ($file);
+ return undef if ($fd eq undef);
+
+ $val = undef;
+
+ # First of all, we must find the line where the section begins
+ while (<$fd>)
+ {
+ chomp;
+ last if (/^$section\:[ \t]*/);
+ }
+
+ while (<$fd>)
+ {
+ chomp;
+
+ # read until the next section arrives
+ last if (/^[^ \t]/);
+
+ next if (/^\#/);
+
+ if (/^[ \t]+(add|set|enable|disable)[ \t]+$key/)
+ {
+ $val = $_;
+ last;
+ }
+ }
+
+ # this is done because commands can be multiline
+ while (<$fd>)
+ {
+ last if (/^[^ \t]/);
+ last if ($val !~ /\\$/);
+
+ s/^[ \t]*/ /;
+ $val =~ s/\\$//;
+ $val .= $_;
+ }
+
+ &gst_file_close ($fd);
+
+ if ($val eq undef)
+ {
+ return undef if ($section eq "default");
+ return &gst_parse_pppconf_common ($file, "default", $key);
+ }
+ else
+ {
+ $val =~ s/\#[^\#]*$//;
+ $val =~ s/[ \t]*$//;
+ $val =~ s/^[ \t]*//;
+ return $val;
+ }
+}
+
+sub gst_parse_pppconf
+{
+ my ($file, $section, $key) = @_;
+ my ($val);
+
+ $val = &gst_parse_pppconf_common ($file, $section, $key);
+
+ if ($val =~ /$key[ \t]+(.+)/)
+ {
+ return $1;
+ }
+}
+
+sub gst_parse_pppconf_bool
+{
+ my ($file, $section, $key) = @_;
+ my ($val);
+
+ $val = &gst_parse_pppconf_common ($file, $section, $key);
+
+ return 1 if ($val ne undef);
+ return 0;
+}
+
+sub gst_parse_pppconf_re
+{
+ my ($file, $section, $key, $re) = @_;
+ my ($val);
+
+ $val = &gst_parse_pppconf_common ($file, $section, $key);
+
+ if ($val =~ /$re/i)
+ {
+ return $1;
+ }
+}
+
+sub gst_parse_confd_net
+{
+ my ($file, $key) = @_;
+ my ($str, $contents, $i);
+
+ $contents = &gst_file_buffer_load ($file);
+
+ for ($i = 0; $i <= scalar (@$contents); $i++)
+ {
+ # search for key
+ if ($$contents[$i] =~ /^$key[ \t]*=[ \t]*\(/)
+ {
+ # contents can be multiline,
+ # just get the first value
+ do {
+ $$contents[$i] =~ /\"([^\"]*)\"/;
+ $str = $1;
+ $i++;
+ } while (!$str);
+ }
+ }
+
+ return $str;
+}
+
+sub gst_parse_confd_net_re
+{
+ my ($file, $key, $re) = @_;
+ my ($str);
+
+ $str = &gst_parse_confd_net ($file, $key);
+
+ if ($str =~ /$re/i)
+ {
+ return $1;
+ }
+}
diff --git a/knetworkconf/backends/platform.pl.in b/knetworkconf/backends/platform.pl.in
new file mode 100644
index 0000000..c81a9e1
--- /dev/null
+++ b/knetworkconf/backends/platform.pl.in
@@ -0,0 +1,685 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Determine the platform we're running on.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Arturo Espinosa <arturo@ximian.com>
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+# --- System guessing --- #
+
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/parse.pl$DOTIN";
+require "$SCRIPTSDIR/xml.pl$DOTIN";
+
+
+$PLATFORM_INFO = {
+ "debian-2.2" => "Debian GNU/Linux 2.2 Potato",
+ "debian-3.0" => "Debian GNU/Linux 3.0 Woody",
+ "debian-3.1" => "Debian GNU/Linux 3.1 Sarge",
+ "debian-4.0" => "Debian GNU/Linux 4.0 Etch",
+ "debian-5.0" => "Debian GNU/Linux 5.0 Lenny",
+ "debian-testing" => "Debian GNU/Linux Testing/Unstable",
+ "ubuntu-5.04" => "Kubuntu 5.04, Hoary Hedgehog",
+ "ubuntu-5.10" => "Kubuntu 5.10, Breezy Badger",
+ "ubuntu-6.06" => "Kubuntu 6.06, Dapper Drake",
+ "ubuntu-6.10" => "Kubuntu 6.10, Edgy Eft",
+ "ubuntu-7.04" => "Kubuntu 7.04, Feisty Fawn",
+ "ubuntu-7.10" => "Kubuntu 7.10, Gutsy Gibbon",
+ "ubuntu-8.04" => "Kubuntu 8.04, Hardy Heron",
+ "redhat-5.2" => "Red Hat Linux 5.2 Apollo",
+ "redhat-6.0" => "Red Hat Linux 6.0 Hedwig",
+ "redhat-6.1" => "Red Hat Linux 6.1 Cartman",
+ "redhat-6.2" => "Red Hat Linux 6.2 Zoot",
+ "redhat-7.0" => "Red Hat Linux 7.0 Guinness",
+ "redhat-7.1" => "Red Hat Linux 7.1 Seawolf",
+ "redhat-7.2" => "Red Hat Linux 7.2 Enigma",
+ "redhat-7.3" => "Red Hat Linux 7.3 Valhalla",
+ "redhat-8.0" => "Red Hat Linux 8.0 Psyche",
+ "redhat-9" => "Red Hat Linux 9.0 Shrike",
+ "openna-1.0" => "OpenNA Linux 1.0 VSLC",
+ "mandrake-7.1" => "Linux Mandrake 7.1",
+ "mandrake-7.2" => "Linux Mandrake 7.2 Odyssey",
+ "mandrake-8.0" => "Linux Mandrake 8.0 Traktopel",
+ "mandrake-9.0" => "Linux Mandrake 9.0 Dolphin",
+ "mandrake-9.1" => "Linux Mandrake 9.1 Bamboo",
+ "mandrake-9.2" => "Linux Mandrake 9.2 FiveStar",
+ "mandrake-10.0" => "Linux Mandrake 10.0",
+ "mandrake-10.1" => "Linux Mandrake 10.1",
+ "mandrake-10.2" => "Linux Mandrake 2005 LE",
+ "mandriva-2006.0" => "Mandriva Linux 2006.0",
+ "mandriva-2006.1" => "Mandriva Linux 2006.1",
+ "mandriva-2007.0" => "Mandriva Linux 2007.0",
+ "mandriva-2007.1" => "Mandriva Linux 2007.1",
+ "yoper-2.2" => "Yoper Linux 2.2",
+ "blackpanther-4.0" => "Black Panther OS 4.0",
+ "conectiva-9" => "Conectiva Linux 9",
+ "conectiva-10" => "Conectiva Linux 10",
+ "suse-7.0" => "SuSE Linux 7.0",
+ "suse-9.0" => "SuSE Linux 9.0",
+ "suse-9.1" => "SuSE Linux 9.1",
+ "turbolinux-7.0" => "Turbolinux 7.0",
+ "slackware-8.0.0" => "Slackware 8.0.0",
+ "slackware-8.1" => "Slackware 8.1",
+ "slackware-9.0.0" => "Slackware 9.0.0",
+ "slackware-9.1.0" => "Slackware 9.1.0",
+ "slackware-10.0.0" => "Slackware 10.0.0",
+ "slackware-10.1.0" => "Slackware 10.1.0",
+ "slackware-10.2.0" => "Slackware 10.2.0",
+ "freebsd-4" => "FreeBSD 4",
+ "freebsd-5" => "FreeBSD 5",
+ "freebsd-6" => "FreeBSD 6",
+ "gentoo" => "Gentoo Linux",
+ "vlos-1.2" => "Vida Linux OS 1.2",
+ "archlinux" => "Arch Linux",
+ "pld-1.0" => "PLD 1.0 Ra",
+ "pld-1.1" => "PLD 1.1 Ra",
+ "pld-1.99" => "PLD 1.99 Ac-pre",
+ "vine-3.0" => "Vine Linux 3.0",
+ "vine-3.1" => "Vine Linux 3.1",
+ "fedora-1" => "Fedora Core 1 (Yarrow)",
+ "fedora-2" => "Fedora Core 2 (Tettnang)",
+ "fedora-3" => "Fedora Core 3 (Heidelberg)",
+ "fedora-4" => "Fedora Core 4 (Stentz)",
+ "fedora-5" => "Fedora Core 5 (Bordeaux)",
+ "rpath" => "rPath Linux",
+ "ark" => "Ark Linux",
+};
+
+sub check_lsb
+{
+ my ($ver, $dist);
+# my %vermap =
+# ("3.0" => "woody");
+
+ my %distmap =
+ ("Debian" => "debian"),
+ ("Mandrake" => "mandrake"),
+ ("Conectiva" => "conectiva"),
+ ("Blackpanther" => "blackpanther");
+
+ # gst_prefix not required here: parse already does that for us.
+ $dist = lc (&gst_parse_sh ("/etc/lsb-release", "DISTRIB_ID"));
+ $ver = lc (&gst_parse_sh ("/etc/lsb-release", "DISTRIB_RELEASE"));
+
+# $ver = $vermap{$ver} if exists $vermap{$ver};
+ $dist = $distmap{$dist} if exists $dirmap{$dir};
+
+ return -1 if ($dist eq "") || ($ver eq "");
+ return "$dist-$ver";
+}
+
+sub check_debian
+{
+ my ($ver, $i);
+ my %vermap =
+ ("testing/unstable" => "testing",
+ "lenny/sid" => "testing",
+ "3.1" => "sarge",
+ "4.0" => "etch",
+ "5.0" => "lenny");
+
+ open DEBIAN, "$gst_prefix/etc/debian_version" or return -1;
+ chomp ($ver = <DEBIAN>);
+ close DEBIAN;
+
+ #if $ver is not found, we will assume it is testing
+ if($ver and exists $vermap{$ver}) {
+ $ver = $vermap{$ver};
+ } else {
+ $ver = "testing";
+ }
+
+ return "debian-$ver";
+}
+
+
+sub check_redhat
+{
+ open RELEASE, "$gst_prefix/etc/redhat-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if (/^Red Hat Linux.*\s+([0-9.]+)\s+.*/)
+ {
+ close RELEASE;
+ return "redhat-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_openna
+{
+ open OPENNA, "$gst_prefix/etc/openna-release" or return -1;
+ while (<OPENNA>)
+ {
+ chomp;
+ if (/^OpenNA*/)
+ {
+ close OPENNA;
+ return "openna-$1";
+ }
+ }
+ close OPENNA;
+ return -1;
+}
+
+sub check_caldera
+{
+ open INSTALLED, "$gst_prefix/etc/.installed" or return -1;
+ while (<INSTALLED>)
+ {
+ chomp;
+ if (/^OpenLinux-(.*)-.*/)
+ {
+ close INSTALLED;
+ return "caldera-$1";
+ }
+ }
+ close INSTALLED;
+ return -1;
+}
+
+
+sub check_suse
+{
+ open RELEASE, "$gst_prefix/etc/SuSE-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if (/^VERSION\s*=\s*(\S+)/)
+ {
+ close RELEASE;
+ return "suse-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_mandrake
+{
+ open MANDRAKE, "$gst_prefix/etc/mandrake-release" or return -1;
+ while (<MANDRAKE>)
+ {
+ $ver = $_;
+ chomp ($ver);
+ if ($ver =~ /^Linux Mandrake release (\S+)/)
+ {
+ close MANDRAKE;
+ return "mandrake-$1";
+ }
+ elsif ($ver =~ /^Mandrake( L|l)inux release ([\d\.]+)/i)
+ {
+ close MANDRAKE;
+ return "mandrake-$2";
+ }
+ }
+ close MANDRAKE;
+ return -1;
+}
+
+sub check_mandriva
+{
+ open MANDRIVA, "$gst_prefix/etc/mandriva-release" or return -1;
+ while (<MANDRIVA>)
+ {
+ $ver = $_;
+ chomp ($ver);
+ if ($ver =~ /^Linux Mandriva release (\S+)/)
+ {
+ close MANDRIVA;
+ return "mandriva-$1";
+ }
+ elsif ($ver =~ /^Mandriva( L|l)inux release ([\d\.]+)/i)
+ {
+ close MANDRIVA;
+ return "mandriva-$2";
+ }
+ }
+ close MANDRIVA;
+ return -1;
+}
+
+sub check_yoper
+{
+ open YOPER, "$gst_prefix/etc/yoper-release" or return -1;
+ while (<YOPER>)
+ {
+ $ver = $_;
+ chomp ($ver);
+ if ($ver =~ m/Yoper (\S+)/)
+ {
+ close YOPER;
+ # find the first digit of our release
+ $mystring= ~m/(\d)/;
+ #store it in $fdigit
+ $fdigit= $1;
+ # the end of the release is marked with -2 so find the -
+ $end = index($ver,"-");
+ $start = index($ver,$fdigit);
+ # extract the substring into $newver
+ $newver= substr($ver,$start,$end-$start);
+ print $newver;
+ return "yoper-$newver";
+ }
+ }
+ close YOPER;
+ return -1;
+}
+
+sub check_blackpanther
+{
+ open BLACKPANTHER, "$gst_prefix/etc/blackPanther-release" or return -1;
+
+ while (<BLACKPANTHER>)
+ {
+ $ver = $_;
+ chomp ($ver);
+ if ($ver =~ /^Linux Black Panther release (\S+)/)
+ {
+ close BLACKPANTHER;
+ return "blackPanther-$1";
+ }
+ elsif ($ver =~ /^Black Panther ( L|l)inux release ([\d\.]+)/i)
+ {
+ close BLACKPANTHER;
+ return "blackPanther-$2";
+ }
+ }
+
+ close BLACKPANTHER;
+ return -1;
+}
+
+sub check_fedora
+{
+ open FEDORA, "$gst_prefix/etc/fedora-release" or return -1;
+ while (<FEDORA>)
+ {
+ $ver = $_;
+ chomp ($ver);
+
+ if ($ver =~ /^Fedora Core release (\S+)/)
+ {
+ close FEDORA;
+ return "fedora-$1";
+ }
+ }
+
+ close FEDORA;
+ return -1;
+}
+
+sub check_rpath
+{
+ open RPATH, "$gst_prefix/etc/distro-release" or return -1;
+
+ while (<RPATH>)
+ {
+ $ver = $_;
+ chomp ($ver);
+
+ if ($ver =~ /^rPath Linux/)
+ {
+ close RPATH;
+ return "rpath";
+ }
+ if ($ver =~ /Foresight/)
+ {
+ close RPATH;
+ return "rpath";
+ }
+ }
+
+ close RPATH;
+ return -1;
+}
+
+sub check_conectiva
+{
+ open RELEASE, "$gst_prefix/etc/conectiva-release" or return -1;
+
+ while (<RELEASE>)
+ {
+ chomp;
+
+ if (/^Conectiva Linux (\S+)/)
+ {
+ close RELEASE;
+ return "conectiva-$1";
+ }
+ }
+
+ close RELEASE;
+ return -1;
+}
+
+sub check_turbolinux
+{
+ open RELEASE, "$gst_prefix/etc/turbolinux-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if (/^Turbolinux\s.*\s([0-9.]+)\s.*/)
+ {
+ close RELEASE;
+ return "turbolinux-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_slackware
+{
+ open RELEASE, "$gst_prefix/etc/slackware-version" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if (/^Slackware ([0-9.]+)/)
+ {
+ close RELEASE;
+ return "slackware-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_gentoo
+{
+ return "gentoo" if stat ("$gst_prefix/usr/portage");
+ return -1;
+}
+
+sub check_vlos
+{
+ open RELEASE, "$gst_prefix/etc/vlos-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if (/^VLOS.*\s+([0-9.]+)/)
+ {
+ close RELEASE;
+ return "vlos-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_archlinux
+{
+ # Since Arch stores gnome in /opt/gnome, use full dir
+ return "archlinux" if stat ("/etc/arch-release");
+ return -1;
+}
+
+sub check_linuxppc
+{
+ open RELEASE, "$gst_prefix/etc/redhat-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if (/^LinuxPPC\s+(\S+)/)
+ {
+ close RELEASE;
+ return "linuxppc-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_pld
+{
+ open RELEASE, "$gst_prefix/etc/pld-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if(/^([0-9.]+) PLD Linux/)
+ {
+ close RELEASE;
+ return "pld-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_vine
+{
+ open RELEASE, "$gst_prefix/etc/vine-release" or return -1;
+ while (<RELEASE>)
+ {
+ chomp;
+ if(/^Vine Linux ([0-9.]+)\s+.*/)
+ {
+ close RELEASE;
+ return "vine-$1";
+ }
+ }
+ close RELEASE;
+ return -1;
+}
+
+sub check_ark
+{
+ open ARK, "$gst_prefix/etc/ark-release" or return -1;
+ while (<ARK>)
+ {
+ $ver = $_;
+ chomp ($ver);
+
+ if ($ver =~ /^Ark Linux/)
+ {
+ close ARK;
+ return "ark";
+ }
+ }
+
+ close ARK;
+ return -1;
+}
+
+sub check_freebsd
+{
+ my ($sysctl_cmd, @output);
+
+ $sysctl_cmd = &gst_file_locate_tool ("sysctl");
+ @output = (readpipe("$sysctl_cmd -n kern.version"));
+ foreach (@output)
+ {
+ chomp;
+ if (/^FreeBSD\s([0-9]+)\.\S+.*/)
+ {
+ return "freebsd-$1";
+ }
+ }
+ return -1;
+}
+
+sub check_solaris
+{
+ my ($fd, $dist);
+
+ #
+ # The file /etc/release is present for solaris-2.6
+ # solaris 2.5 does not have the file. Solaris-7.0 and 8.0 have not
+ # been checked
+ #
+ # uname output
+ # Solaris 2.5: 5.5(.1)
+ # Solaris 2.6: 5.6
+ # Solaris 7: unknown, assume 7.0
+ # Solaris 8: unknown, assume 8.0
+ #
+ $fd = &gst_file_run_pipe_read ("uname -r");
+ return -1 if $fd eq undef;
+ chomp ($dist = <$fd>);
+ &gst_file_close ($fd);
+
+ if ($dist =~ /^5\.(\d)/) { return "solaris-2.$1" }
+ else { if ($dist =~ /^([78])\.\d/) { return "solaris-$1.0" } }
+ return -1;
+}
+
+sub gst_platform_get_system
+{
+ my ($tool) = @_;
+
+ # get the output of 'uname -s', it returns the system we are running
+ $$tool{"system"} = &gst_file_run_backtick ("uname -s");
+ chomp ($$tool{"system"});
+}
+
+sub gst_platform_guess
+{
+ my ($tool) = @_;
+
+ my %check = (
+ # Red Hat check must run after Vine, Mandrake and Fedora, and Mandrake after BlackPanther
+ "Linux" => [ \&check_lsb, \&check_debian, \&check_caldera, \&check_suse, \&check_blackpanther, \&check_vine,
+ \&check_fedora, \&check_mandrake, \&check_mandriva, \&check_conectiva, \&check_linuxppc, \&check_redhat, \&check_openna,
+ \&check_turbolinux, \&check_slackware, \&check_vlos, \&check_gentoo, \&check_pld, \&check_rpath, \&check_archlinux, \&check_ark ],
+ "FreeBSD" => [ \&check_freebsd ],
+ "SunOS" => [ \&check_solaris ]
+ );
+ my $plat;
+
+ # Fool-the-backend hack.
+ if (exists $ENV{"GST_DIST"})
+ {
+ $$tool{"platform"} = $gst_dist = $ENV{"GST_DIST"};
+ return;
+ }
+
+ foreach $plat (keys %check)
+ {
+ if ($$tool{"system"} =~ /$plat/)
+ {
+ my ($check, $dist);
+
+ foreach $check (@{$check{$plat}})
+ {
+ $dist = &$check ();
+ if ($dist != -1)
+ {
+ $$tool{"platform"} = $gst_dist = $dist;
+ return;
+ }
+ }
+ }
+ }
+
+ $$tool{"platform"} = $gst_dist = "unknown";
+}
+
+
+# gst_platform_ensure_supported
+#
+# Takes a list of supported platforms and sees if the one detected is found in
+# this list. If not, will report a list of supported platforms and fail.
+
+sub gst_platform_ensure_supported
+{
+ my ($tool, @supported) = @_;
+
+ $$tool{"platforms"} = [ @supported ];
+
+ foreach $platform (@supported)
+ {
+ if ($platform eq $$tool{"platform"})
+ {
+ &gst_report ("platform_success", $platform, $$PLATFORM_INFO{$platform});
+ return;
+ }
+ }
+
+ # Not supported.
+ if (exists $$tool{"platform"})
+ {
+ &gst_report ("platform_unsup", $$tool{"platform"});
+ }
+ else
+ {
+ &gst_report ("platform_undet");
+ }
+}
+
+
+# A directive handler that sets the currently selected platform.
+sub gst_platform_set
+{
+ my ($tool, $platform) = @_;
+ my ($p);
+
+ foreach $p (@{ $$tool{"platforms"}})
+ {
+ if ($p eq $platform)
+ {
+ $$tool{"platform"} = $gst_dist = $platform;
+ &gst_report ("platform_success", $platform, $$PLATFORM_INFO{$platform});
+ &gst_report_end ();
+ return;
+ }
+ }
+
+ &gst_report ("platform_unsup", $platform);
+ &gst_report_end ();
+}
+
+sub gst_platform_print_list
+{
+ my ($platforms) = @_;
+ my ($platform, $name);
+
+ &gst_xml_print_begin ("platforms");
+ foreach $platform (sort @$platforms)
+ {
+ $name = $$PLATFORM_INFO{$platform};
+
+ &gst_xml_container_enter ("platform");
+ &gst_xml_print_line ("<key>$platform</key>");
+ &gst_xml_print_line ("<name>$name</name>");
+ &gst_xml_container_leave ();
+ }
+ &gst_xml_print_end ("platforms");
+}
+
+sub gst_platform_list
+{
+ my ($tool) = @_;
+
+ &gst_report_end ();
+ &gst_platform_print_list ($$tool{"platforms"});
+}
+
+1;
diff --git a/knetworkconf/backends/process.pl.in b/knetworkconf/backends/process.pl.in
new file mode 100644
index 0000000..c1047d6
--- /dev/null
+++ b/knetworkconf/backends/process.pl.in
@@ -0,0 +1,54 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Common process stuff for the setup tools backends.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Carlos Garnacho Parro <carlosg@gnome.org>
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/general.pl$DOTIN";
+require "$SCRIPTSDIR/file.pl$DOTIN";
+
+sub gst_process_kill_by_pidfile
+{
+ my ($pidfile) = @_;
+ my ($buf, $pid);
+
+ if ($pidfile !~ /^\//)
+ {
+ # add default pidfiles path if it isn't full path
+ $pidfile = "/var/run/" . $pidfile;
+ }
+
+ if (&gst_file_exists ($pidfile))
+ {
+ $buf = &gst_file_buffer_load ($pidfile);
+ $pid = $$buf[0];
+
+ &gst_file_run ("kill -9 $pid");
+ }
+}
+
+1;
diff --git a/knetworkconf/backends/replace.pl.in b/knetworkconf/backends/replace.pl.in
new file mode 100644
index 0000000..79e5cf2
--- /dev/null
+++ b/knetworkconf/backends/replace.pl.in
@@ -0,0 +1,1770 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# replace.pl: Common in-line replacing stuff for the ximian-setup-tools backends.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Arturo Espinosa <arturo@ximian.com>
+# Michael Vogt <mvo@debian.org> - Debian 2.[2|3] support.
+# David Lee Ludwig <davidl@wpi.edu> - Debian 2.[2|3] support.
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/util.pl$DOTIN";
+require "$SCRIPTSDIR/file.pl$DOTIN";
+require "$SCRIPTSDIR/parse.pl$DOTIN";
+
+
+# General rules: all replacing is in-line. Respect unsupported values, comments
+# and as many spacing as possible.
+
+# The concept of keyword (kw) here is a key, normaly in its own line, whose
+# boolean representation is its own existence.
+
+# A $re is a regular expression. In most functions here, regular expressions
+# are converted to simple separators, by using gst_replace_regexp_to_separator.
+# This makes it easier to convert a parse table into a replace table.
+
+# Every final replacing function to be used by a table must handle one key
+# at a time, but may replace several values from there.
+#
+# Return 0 for success, and -1 for failure.
+#
+# Most of these functions have a parsing counterpart. The convention is
+# that parse becomes replace and split becomes join:
+# gst_parse_split_first_str -> gst_replace_join_first_str
+
+# Additional abstraction: replace table entries can have
+# arrays inside. The replace proc will be ran with every
+# combination that the arrays provide. Ex:
+# ["user", \&gst_replace_foo, [0, 1], [2, 3] ] will replace
+# using all possibilities in the combinatory of [0, 1]x[2, 3].
+# Check RedHat 7.2's network replace table for further
+# enlightenment.
+sub gst_replace_run_entry
+{
+ my ($values_hash, $key, $proc, $cp, $value) = @_;
+ my ($ncp, $i, $j, $res);
+
+ $ncp = [@$cp];
+ for ($i = 0; $i < scalar (@$cp); $i ++)
+ {
+ if (ref $$cp[$i] eq "ARRAY")
+ {
+ foreach $j (@{$$cp[$i]})
+ {
+ $$ncp[$i] = $j;
+ $res = -1 if &gst_replace_run_entry ($values_hash, $key, $proc, $ncp, $value);
+ }
+ return $res;
+ }
+ }
+
+ # OK, the given entry didn't have any array refs in it...
+
+ &gst_debug_print_line ("gst_replace_from_table: $key");
+ return -1 if (!&gst_parse_replace_hash_values ($ncp, $values_hash));
+ push (@$ncp, $$values_hash{$key}) unless $key eq "_always_";
+ $res = -1 if &$proc (@$ncp);
+ return $res;
+}
+
+# gst_replace_from_table takes a file mapping, a replace table, a hash
+# of values, probably made from XML parsing, and whose keys are
+# the same keys the table handles.
+#
+# Table entries whose keys are not present in the values_hash
+# will not be processed. More than one entry may process the same key.
+#
+# The functions in the replace tables, most of which are coded in
+# this file, receive the mapped files of the first argument, and then
+# a set of values. The last argument is the value of the $values_hash
+# for the corresponding key of the entry.
+sub gst_replace_from_table
+{
+ my ($fn, $table, $values_hash, $old_hash) = @_;
+ my ($key, $proc, @param);
+ my ($i, @cp, @files, $res);
+
+ $$fn{"OLD_HASH"} = $old_hash;
+
+ foreach $i (@$table)
+ {
+ @cp = @$i;
+ $key = shift (@cp);
+
+ $proc = shift (@cp);
+ @files = &gst_parse_replace_files (shift (@cp), $fn);
+ unshift @cp, @files if (scalar @files) > 0;
+
+ if ((exists $$values_hash{$key}) or ($key eq "_always_"))
+ {
+ $res = &gst_replace_run_entry ($values_hash, $key, $proc, \@cp, $$values_hash{$key});
+ }
+ elsif ((!exists $$values_hash{$key}) && (exists $$old_hash{$key}))
+ {
+ # we need to remove all the instances of the known variables that doesn't exist in the XML
+ $res = &gst_replace_run_entry ($values_hash, $key, $proc, \@cp, undef);
+ }
+ }
+
+ return $res;
+}
+
+# Wacky function that tries to create a field separator from a regular expression.
+# Doesn't work with all possible regular expressions: just with the ones we are working with.
+sub gst_replace_regexp_to_separator
+{
+ $_ = $_[0];
+
+ s/\[([^^])([^\]])[^\]]*\]/$1/g;
+ s/\+//g;
+ s/\$//g;
+ s/[^\*]\*//g;
+
+ return $_;
+}
+
+sub is_array_ref
+{
+ my $val;
+
+ return 1 if (ref ($val) eq "ARRAY");
+ return 0 if (ref ($val) eq undef);
+
+ &gst_debug_print_line ("is_array_ref: We shouldn't be here!");
+
+ return 0;
+}
+
+sub set_value
+{
+ my ($key, $val, $re) = @_;
+
+ return $key . &gst_replace_regexp_to_separator ($re) . $val;
+}
+
+# Edit a $file, wich is assumed to have a column-based format, with $re matching field separators
+# and one record per line. Search for lines with the corresponding $key.
+# The last arguments can be any number of standard strings.
+sub gst_replace_split
+{
+ my ($file, $key, $re, @value) = @_;
+ my ($fd, @line, @res);
+ my ($buff, $i);
+ my ($pre_space, $post_comment);
+ my ($line_key, $val, $ret);
+
+ &gst_report_enter ();
+ &gst_report ("replace_split", $key, $file);
+
+ $buff = &gst_file_buffer_load ($file);
+
+ foreach $i (@$buff)
+ {
+ $pre_space = $post_comment = "";
+
+ chomp $i;
+ $pre_space = $1 if $i =~ s/^([ \t]+)//;
+ $post_comment = $1 if $i =~ s/([ \t]*\#.*)//;
+
+ if ($i ne "")
+ {
+ @line = split ($re, $i, 2);
+ $line_key = shift (@line);
+
+ # found the key?
+ if ($line_key eq $key)
+ {
+ shift (@value) while ($value[0] eq "" && (scalar @value) > 0);
+
+ if ((scalar @value) == 0)
+ {
+ $i = "";
+ next;
+ }
+
+ $val = shift (@value);
+
+ chomp $val;
+ $i = &set_value ($key, $val, $re);
+ }
+ }
+
+ $i = $pre_space . $i . $post_comment . "\n";
+ }
+
+ foreach $i (@value)
+ {
+ push (@$buff, &set_value ($key, $i, $re) . "\n") if ($i ne "");
+ }
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+# Replace all key/values in file with those in @$value,
+# deleting exceeding ones and appending those required.
+sub gst_replace_join_all
+{
+ my ($file, $key, $re, $value) = @_;
+
+ return &gst_replace_split ($file, $key, $re, @$value);
+}
+
+# Find first $key value and replace with $value. Append if not found.
+sub gst_replace_join_first_str
+{
+ my ($file, $key, $re, $value) = @_;
+
+ return &gst_replace_split ($file, $key, $re, $value);
+}
+
+# Treat value as a bool value, using val_off and val_on as corresponding
+# boolean representations.
+sub gst_replace_join_first_bool
+{
+ my ($file, $key, $re, $val_on, $val_off, $value) = @_;
+
+ # Fixme: on and off should be a parameter.
+ $value = ($value == 1)? $val_on: $val_off;
+
+ return &gst_replace_split ($file, $key, $re, $value);
+}
+
+# Find first key in file, and set array join as value.
+sub gst_replace_join_first_array
+{
+ my ($file, $key, $re1, $re2, $value) = @_;
+
+ return &gst_replace_split ($file, $key, $re1, join (&gst_replace_regexp_to_separator ($re2), @$value));
+}
+
+# Escape $value in /bin/sh way, find/append key and set escaped value.
+sub gst_replace_sh
+{
+ my ($file, $key, $value) = @_;
+ my $ret;
+
+ $value = &gst_parse_shell_escape ($value);
+
+ &gst_report_enter ();
+ &gst_report ("replace_sh", $key, $file);
+
+ # This will expunge the whole var if the value is empty.
+ if ($value eq "")
+ {
+ $ret = &gst_replace_split ($file, $key, "[ \t]*=[ \t]*");
+ }
+ else
+ {
+ $ret = &gst_replace_split ($file, $key, "[ \t]*=[ \t]*", $value);
+ }
+
+ &gst_report_leave ();
+ return $ret;
+}
+
+# Escape $value in /bin/sh way, find/append key and set escaped value, make sure line har
+sub gst_replace_sh_export
+{
+ my ($file, $key, $value) = @_;
+ my $ret;
+
+ $value = &gst_parse_shell_escape ($value);
+
+ # This will expunge the whole var if the value is empty.
+
+ # FIXME: Just adding "export " works for the case I need, though it doesn't
+ # handle arbitraty whitespace. Something should be written to replace gst_replace_split()
+ # here.
+
+ if ($value eq "")
+ {
+ $ret = &gst_replace_split ($file, "export " . $key, "[ \t]*=[ \t]*");
+ }
+ else
+ {
+ $ret = &gst_replace_split ($file, "export " . $key, "[ \t]*=[ \t]*", $value);
+ }
+
+ return $ret;
+}
+
+# Treat value as a yes/no bool, replace in shell style.
+# val_true and val_false have default yes/no values.
+# use &gst_replace_sh_bool (file, key, value) if defaults are desired.
+sub gst_replace_sh_bool
+{
+ my ($file, $key, $val_true, $val_false, $value) = @_;
+
+ # default value magic.
+ if ($val_false eq undef)
+ {
+ $value = $val_true;
+ $val_true = undef;
+ }
+
+ $val_true = "yes" unless $val_true;
+ $val_false = "no" unless $val_false;
+
+ $value = ($value == 1)? $val_true: $val_false;
+
+ return &gst_replace_sh ($file, $key, $value);
+}
+
+# Treat value as a yes/no bool, replace in export... shell style.
+sub gst_replace_sh_export_bool
+{
+ my ($file, $key, $val_true, $val_false, $value) = @_;
+
+ # default value magic.
+ if ($val_false eq undef)
+ {
+ $value = $val_true;
+ $val_true = undef;
+ }
+
+ $val_true = "yes" unless $val_true;
+ $val_false = "no" unless $val_false;
+
+ $value = ($value == 1)? $val_true: $val_false;
+
+ return &gst_replace_sh_export ($file, $key, $value);
+}
+
+# Get a fully qualified hostname from a $key shell var in $file
+# and set the hostname part. e.g.: suse70's /etc/rc.config's FQHOSTNAME.
+sub gst_replace_sh_set_hostname
+{
+ my ($file, $key, $value) = @_;
+ my ($domain);
+
+ $domain = &gst_parse_sh_get_domain ($file, $key);
+ return &gst_replace_sh ($file, $key, "$value.$domain");
+}
+
+# Get a fully qualified hostname from a $key shell var in $file
+# and set the domain part. e.g.: suse70's /etc/rc.config's FQHOSTNAME.
+sub gst_replace_sh_set_domain
+{
+ my ($file, $key, $value) = @_;
+ my ($hostname);
+
+ $hostname = &gst_parse_sh_get_hostname ($file, $key);
+ return &gst_replace_sh ($file, $key, "$hostname.$value");
+}
+
+# Join the array pointed by $value with the corresponding $re separator
+# and assign that to the $key shell variable in $file.
+sub gst_replace_sh_join
+{
+ my ($file, $key, $re, $value) = @_;
+
+ return &gst_replace_sh ($file, $key,
+ join (&gst_replace_regexp_to_separator ($re), @$value));
+}
+
+# replace a regexp with $value
+sub gst_replace_sh_re
+{
+ my ($file, $key, $re, $value) = @_;
+ my ($val);
+
+ $val = &gst_parse_sh ($file, $key);
+
+ if ($val =~ /$re/)
+ {
+ $val =~ s/$re/$value/;
+ }
+ else
+ {
+ $val .= $value;
+ }
+
+ $val = '"' . $val . '"' if ($val !~ /^\".*\"$/);
+
+ return &gst_replace_split ($file, $key, "[ \t]*=[ \t]*", $val)
+}
+
+# Quick trick to set a keyword $key in $file. (think /etc/lilo.conf keywords).
+sub gst_replace_kw
+{
+ my ($file, $key, $value) = @_;
+ my $ret;
+
+ &gst_report_enter ();
+ &gst_report ("replace_kw", $key, $file);
+ $ret = &gst_replace_split ($file, $key, "\$", ($value)? "\n" : "");
+ &gst_report_leave ();
+ return $ret;
+}
+
+# The kind of $file whose $value is its first line contents.
+# (/etc/hostname)
+sub gst_replace_line_first
+{
+ my ($file, $value) = @_;
+ my $fd;
+
+ &gst_report_enter ();
+ &gst_report ("replace_line_first", $file);
+ $fd = &gst_file_open_write_from_names ($file);
+ &gst_report_leave ();
+ return -1 if !$fd;
+
+ print $fd "$value\n";
+ &gst_file_close ($fd);
+
+ return 0;
+}
+
+# For every key in %$value, replace/append the corresponding key/value pair.
+# The separator for $re1
+sub gst_replace_join_hash
+{
+ my ($file, $re1, $re2, $value) = @_;
+ my ($i, $res, $tmp, $val);
+ my ($oldhash, %merge);
+
+ $oldhash = &gst_parse_split_hash ($file, $re1, $re2);
+ foreach $i (keys (%$value), keys (%$oldhash))
+ {
+ $merge{$i} = 1;
+ }
+
+ $res = 0;
+
+ foreach $i (keys (%merge))
+ {
+ if (exists $$value{$i})
+ {
+ $val = join (&gst_replace_regexp_to_separator ($re2), @{$$value{$i}});
+ $tmp = &gst_replace_split ($file, $i, $re1, $val);
+ }
+ else
+ {
+ # This deletes the entry.
+ $tmp = &gst_replace_split ($file, $i, $re1);
+ }
+ $res = $tmp if !$res;
+ }
+
+ return $res;
+}
+
+# Find $re matching send string and replace parenthesyzed
+# part of $re with $value. FIXME: apply meeks' more general impl.
+sub gst_replace_chat
+{
+ my ($file, $re, $value) = @_;
+ my ($buff, $i, $bak, $found, $substr, $ret);
+
+ &gst_report_enter ();
+ &gst_report ("replace_chat", $file);
+ $buff = &gst_file_buffer_load ($file);
+
+ SCAN: foreach $i (@$buff)
+ {
+ $bak = "";
+ $found = "";
+ my ($quoted);
+ chomp $i;
+
+ while ($i ne "")
+ {
+ # If it uses quotes. FIXME: Assuming they surround the whole string.
+ if ($i =~ /^\'/)
+ {
+ $i =~ s/\'([^\']*)\' ?//;
+ $found = $1;
+ $quoted = 1;
+ }
+ else
+ {
+ $i =~ s/([^ \t]*) ?//;
+ $found = $1;
+ $quoted = 0;
+ }
+
+ # If it looks like what we're looking for,
+ # substitute what is in parens with value.
+ if ($found =~ /$re/i)
+ {
+ $substr = $1;
+ $found =~ s/$substr/$value/i;
+
+ if ($quoted == 1)
+ {
+ $i = $bak . "\'$found\' " . $i . "\n";
+ }
+ else
+ {
+ $i = $bak . "$found " . $i . "\n";
+ }
+
+ last SCAN;
+ }
+
+ if ($quoted == 1)
+ {
+ $bak .= "\'$found\'";
+ }
+ else
+ {
+ $bak .= "$found";
+ }
+
+ $bak .= " " if $bak ne "";
+ }
+
+ $i = $bak . "\n";
+ }
+
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+# Find/append $section in ini $file and replace/append
+# $var = $value pair. FIXME: should reimplement with
+# interfaces style. This is too large.
+sub gst_replace_ini
+{
+ my ($file, $section, $var, $value) = @_;
+ my ($buff, $i, $found_flag, $ret);
+ my ($pre_space, $post_comment, $sec_save);
+
+ &gst_report_enter ();
+ &gst_report ("replace_ini", $var, $section, $file);
+
+ $buff = &gst_file_buffer_load ($file);
+
+ &gst_file_buffer_join_lines ($buff);
+ $found_flag = 0;
+
+ foreach $i (@$buff)
+ {
+ $pre_space = $post_comment = "";
+
+ chomp $i;
+ $pre_space = $1 if $i =~ s/^([ \t]+)//;
+ $post_comment = $1 if $i =~ s/([ \t]*[\#;].*)//;
+
+ if ($i ne "")
+ {
+ if ($i =~ /\[$section\]/i)
+ {
+ $i =~ s/(\[$section\][ \t]*)//i;
+ $sec_save = $1;
+ $found_flag = 1;
+ }
+
+ if ($found_flag)
+ {
+ if ($i =~ /\[[^\]]+\]/)
+ {
+ $i = "$var = $value\n$i" if ($value ne "");
+ $found_flag = 2;
+ }
+
+ if ($i =~ /^$var[ \t]*=/i)
+ {
+ if ($value ne "")
+ {
+ $i =~ s/^($var[ \t]*=[ \t]*).*/$1$value/i;
+ }
+ else
+ {
+ $i = "";
+ }
+ $found_flag = 2;
+ }
+ }
+ }
+
+ if ($found_flag && $sec_save ne "")
+ {
+ $i = $sec_save . $i;
+ $sec_save = "";
+ }
+
+ $i = $pre_space . $i . $post_comment . "\n";
+ last if $found_flag == 2;
+ }
+
+ push @$buff, "\n[$section]\n" if (!$found_flag);
+ push @$buff, "$var = $value\n" if ($found_flag < 2 && $value ne "");
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+# Well, removes a $section from an ini type $file.
+sub gst_replace_remove_ini_section
+{
+ my ($file, $section) = @_;
+ my ($buff, $i, $found_flag, $ret);
+ my ($pre_space, $post_comment, $sec_save);
+
+ &gst_report_enter ();
+ &gst_report ("replace_del_ini_sect", $section, $file);
+
+ $buff = &gst_file_buffer_load ($file);
+
+ &gst_file_buffer_join_lines ($buff);
+ $found_flag = 0;
+
+ foreach $i (@$buff)
+ {
+ $pre_space = $post_comment = "";
+
+ chomp $i;
+ $pre_space = $1 if $i =~ s/^([ \t]+)//;
+ $post_comment = $1 if $i =~ s/([ \t]*[\#;].*)//;
+
+ if ($i ne "")
+ {
+ if ($i =~ /\[$section\]/i)
+ {
+ $i =~ s/(\[$section\][ \t]*)//i;
+ $found_flag = 1;
+ }
+ elsif ($found_flag && $i =~ /\[.+\]/i)
+ {
+ $i = $pre_space . $i . $post_comment . "\n";
+ last;
+ }
+ }
+
+ if ($found_flag)
+ {
+ if ($post_comment =~ /^[ \t]*$/)
+ {
+ $i = "";
+ }
+ else
+ {
+ $i = $post_comment . "\n";
+ }
+ }
+ else
+ {
+ $i = $pre_space . $i . $post_comment . "\n";
+ }
+ }
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+# Removes a $var in $section of a ini type $file.
+sub gst_replace_remove_ini_var
+{
+ my ($file, $section, $var) = @_;
+ &gst_replace_ini ($file, $section, $var, "");
+}
+
+# Replace using boolean $value with a yes/no representation,
+# ini style.
+sub gst_replace_ini_bool
+{
+ my ($file, $section, $var, $value) = @_;
+
+ $value = ($value == 1)? "yes": "no";
+
+ return &gst_replace_ini ($file, $section, $var, $value);
+}
+
+# *cap replacement methods.
+#sub gst_replace_cap
+#{
+# my ($file, $section, $var, $value) = @_;
+# my ($buff, $i, $found_flag, $ret);
+# my ($pre_space, $post_comment, $sec_save);
+#
+# $buff = &gst_file_buffer_load ($file);
+## &gst_file_buffer_join_lines ($buff);
+# $found_flag = 0;
+#
+# foreach $i (@$buff)
+# {
+# $pre_space = $post_comment = "";
+#
+# chomp $i;
+# $pre_space = $1 if $i =~ s/^([ \t]+)//;
+# $post_comment = $1 if $i =~ s/^([ \t]*[\#].*)//;
+#
+# if ($i ne "")
+# {
+# if ($i =~ /^$section[|:]/i)
+# {
+# $i =~ s/^($section)//i;
+# $sec_save = $1;
+# $found_flag = 1;
+# }
+#
+# if ($found_flag)
+# {
+# if ($i =~ /^[a-z0-9]+[|:]/)
+# {
+# $i = "\t:$var=$value:\n$i";
+# $found_flag = 2;
+# }
+#
+# if ($found_flag && $i =~ /^:$var[=:]/i)
+# {
+# if ($value ne "")
+# {
+# $i =~ s/^(:$var)[^:]*/$1=$value/i;
+# }
+# else
+# {
+# $i = "";
+# }
+# $found_flag = 2;
+# }
+# }
+# }
+#
+# if ($found_flag && $sec_save ne "")
+# {
+# $i = $sec_save . $i;
+# $sec_save = "";
+# }
+#
+# $i = $pre_space . $i . $post_comment . "\n";
+# last if $found_flag == 2;
+# }
+#
+# push @$buff, "\n$section:\\\n" if (!$found_flag);
+# push @$buff, "\t:$var=$value:\n" if ($found_flag < 2 && $value ne "");
+#
+# &gst_file_buffer_clean ($buff);
+# $ret = &gst_file_buffer_save ($buff, $file);
+# return $ret;
+#}
+
+sub gst_replace_remove_cap_section
+{
+ my ($file, $section) = @_;
+ my ($buff, $i, $found_flag, $ret);
+ my ($pre_space, $post_comment, $sec_save);
+
+ $buff = &gst_file_buffer_load ($file);
+ $found_flag = 0;
+
+ foreach $i (@$buff)
+ {
+ $pre_space = $post_comment = "";
+
+ chomp $i;
+ $pre_space = $1 if $i =~ s/^([ \t]+)//;
+ $post_comment = $1 if $i =~ s/^([ \t]*[\#].*)//;
+
+ if ($i ne "")
+ {
+ if ($i =~ /^$section[|:]/i)
+ {
+ $i = "";
+ $found_flag = 1;
+ }
+ elsif ($found_flag && $i =~ /^[a-z0-9]+[|:]/i)
+ {
+ $i = $pre_space . $i . $post_comment . "\n";
+ last;
+ }
+ }
+
+ if ($found_flag)
+ {
+ if ($post_comment =~ /^[ \t]*$/)
+ {
+ $i = "";
+ }
+ else
+ {
+ $i = $post_comment . "\n";
+ }
+ }
+ else
+ {
+ $i = $pre_space . $i . $post_comment . "\n";
+ }
+ }
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ return $ret;
+}
+
+# Save a printcap buffer to file. This doesn't do any extra processing for now,
+# but it may do so in the future.
+sub gst_replace_printcap_buffer_save
+{
+ my ($file, $buf) = @_;
+ my $ret;
+
+ &gst_file_buffer_clean ($buf);
+ $ret = &gst_file_buffer_save ($buf, $file);
+ return $ret;
+}
+
+sub gst_replace_printcap_print_stanza
+{
+ my ($stanza) = @_;
+ return $stanza . ":\n";
+}
+
+sub gst_replace_printcap_print_option
+{
+ my ($option, $type, $value) = @_;
+ return "\t:" . $option . $type . $value . ":\n";
+}
+
+sub gst_replace_printcap_add_stanza
+{
+ my ($buf, $stanza) = @_;
+
+ push @$buf, "\n";
+ push @$buf, "##PRINTTOOL3## LOCAL unknown NAxNA {} Unknown Default {}\n";
+ push @$buf, &gst_replace_printcap_print_stanza ($stanza);
+
+ return ($#$buf - 1, $#$buf);
+}
+
+sub gst_replace_printcap_add_option_slot
+{
+ my ($buf, $stanza_line_no) = @_;
+ my (@buf_tail);
+
+ @buf_tail = splice (@$buf, $stanza_line_no + 1);
+ push @$buf, "\t:NEW_OPTION:\n";
+ push @$buf, @buf_tail;
+
+ return $stanza_line_no + 1;
+}
+
+sub gst_replace_printcap_remove_stanza_from_buf
+{
+ my ($buf, $printtool_line_no, $stanza_line_no) = @_;
+ my ($next_printtool_line_no, $next_stanza_line_no);
+ my ($splice_start, $splice_end);
+
+ ($next_printtool_line_no, $next_stanza_line_no) =
+ &gst_parse_printcap_get_next_stanza ($buf, $stanza_line_no + 1);
+
+ if ($printtool_line_no != -1)
+ {
+ $splice_start = $printtool_line_no;
+ }
+ else
+ {
+ $splice_start = $stanza_line_no;
+ }
+
+ if ($next_printtool_line_no != -1)
+ {
+ $splice_end = $next_printtool_line_no;
+ }
+ else
+ {
+ $splice_end = $next_stanza_line_no;
+ }
+
+ if ($splice_end != -1)
+ {
+ splice (@$buf, $splice_start, $splice_end - $splice_start);
+ }
+ else
+ {
+ splice (@$buf, $splice_start);
+ }
+}
+
+sub gst_replace_printcap_remove_option_slot
+{
+ my ($buf, $option_line_no) = @_;
+ splice (@$buf, $option_line_no, 1);
+}
+
+# High-level API.
+sub gst_replace_printcap_remove_printer
+{
+ my ($file, $printer) = @_;
+ my ($buf, $printtool_line_no, $stanza_line_no);
+
+ $buf = &gst_parse_printcap_buffer_load ($file);
+
+ ($printtool_line_no, $stanza_line_no) = &gst_parse_printcap_find_stanza ($buf, 0, $printer);
+ &gst_replace_printcap_remove_stanza_from_buf ($buf, $printtool_line_no, $stanza_line_no);
+
+ $ret = &gst_replace_printcap_buffer_save ($file, $buf);
+ return $ret;
+}
+
+# High-level API.
+sub gst_replace_printcap
+{
+ my ($file, $section, $var, $type, $value) = @_;
+ my ($printtool_line_no, $stanza_line_no, $option_line_no);
+ my ($buf, $ret);
+
+ $buf = &gst_parse_printcap_buffer_load ($file);
+
+ ($printtool_line_no, $stanza_line_no) = &gst_parse_printcap_find_stanza ($buf, 0, $section);
+ if ($stanza_line_no == -1)
+ {
+ ($printtool_line_no, $stanza_line_no) = &gst_replace_printcap_add_stanza ($buf, $section);
+ }
+
+ $option_line_no = &gst_parse_printcap_find_option ($buf, $stanza_line_no + 1, $var);
+ if ($option_line_no == -1)
+ {
+ $option_line_no = &gst_replace_printcap_add_option_slot ($buf, $stanza_line_no);
+ }
+
+ if ($type ne "")
+ {
+ $$buf [$option_line_no] = "\t:" . $var . $type . $value . ":\n";
+ }
+ elsif ($value == 1)
+ {
+ $$buf [$option_line_no] = "\t:" . $var . ":\n";
+ }
+ else
+ {
+ &gst_replace_printcap_remove_option_slot ($buf, $option_line_no);
+ }
+
+ $ret = &gst_replace_printcap_buffer_save ($file, $buf);
+ return $ret;
+}
+
+# Debian /etc/network/interfaces in-line replacing methods.
+
+# From loaded buffer, starting at $line_no, find next debian
+# interfaces format stanza. Return array ref with all stanza args.
+# -1 if not found.
+# NOTE: $line_no is a scalar ref. and gives the position of next stanza.
+sub gst_replace_interfaces_get_next_stanza
+{
+ my ($buff, $line_no, $stanza_type) = @_;
+ my ($i, $line);
+
+ while ($$line_no < (scalar @$buff))
+ {
+ $_ = $$buff[$$line_no];
+ $_ = &gst_parse_interfaces_line_clean ($_);
+
+ if (/^$stanza_type[ \t]+[^ \t]/)
+ {
+ s/^$stanza_type[ \t]+//;
+ return [ split ("[ \t]+", $_) ];
+ }
+ $$line_no ++;
+ }
+
+ return -1;
+}
+
+sub gst_replace_interfaces_line_is_stanza
+{
+ my ($line) = @_;
+
+ return 1 if $line =~ /^(iface|auto|mapping)[ \t]+[^ \t]/;
+ return 0;
+}
+
+# Scan for next option. An option is something that is
+# not a stanza. Return key/value tuple ref, -1 if not found.
+# $$line_no will contain position.
+sub gst_replace_interfaces_get_next_option
+{
+ my ($buff, $line_no) = @_;
+ my ($i, $line, $empty_lines);
+
+ $empty_lines = 0;
+
+ while ($$line_no < (scalar @$buff))
+ {
+ $_ = $$buff[$$line_no];
+ $_ = &gst_parse_interfaces_line_clean ($_);
+
+ if (!/^$/)
+ {
+ return [ split ("[ \t]+", $_, 2) ] if (! &gst_replace_interfaces_line_is_stanza ($_));
+ $$line_no -= $empty_lines;
+ return -1;
+ }
+ else
+ {
+ $empty_lines ++;
+ }
+
+ $$line_no ++;
+ }
+
+ $$line_no -= $empty_lines;
+ return -1;
+}
+
+# Search buffer for option with key $key, starting
+# at $$line_no position. Return 1/0 found result.
+# $$line_no will show position.
+sub gst_replace_interfaces_option_locate
+{
+ my ($buff, $line_no, $key) = @_;
+ my $option;
+
+ while (($option = &gst_replace_interfaces_get_next_option ($buff, $line_no)) != -1)
+ {
+ return 1 if ($$option[0] eq $key);
+ $$line_no ++;
+ }
+
+ return 0;
+}
+
+# Locate stanza line for $iface in $buff, starting at $$line_no.
+sub gst_replace_interfaces_next_stanza_locate
+{
+ my ($buff, $line_no) = @_;
+
+ return &gst_replace_interfaces_get_next_stanza ($buff, \$$line_no, "(iface|auto|mapping)");
+}
+
+sub gst_replace_interfaces_iface_stanza_locate
+{
+ my ($buff, $line_no, $iface) = @_;
+
+ return &gst_replace_interfaces_generic_stanza_locate ($buff, \$$line_no, $iface, "iface");
+}
+
+sub gst_replace_interfaces_auto_stanza_locate
+{
+ my ($buff, $line_no, $iface) = @_;
+
+ return &gst_replace_interfaces_generic_stanza_locate ($buff, \$$line_no, $iface, "auto");
+}
+
+sub gst_replace_interfaces_generic_stanza_locate
+{
+ my ($buff, $line_no, $iface, $stanza_name) = @_;
+ my $stanza;
+
+ while (($stanza = &gst_replace_interfaces_get_next_stanza ($buff, \$$line_no, $stanza_name)) != -1)
+ {
+ return 1 if ($$stanza[0] eq $iface);
+ $$line_no++;
+ }
+
+ return 0;
+}
+
+# Create a Debian Woody stanza, type auto, with the requested
+# @ifaces as values.
+sub gst_replace_interfaces_auto_stanza_create
+{
+ my ($buff, @ifaces) = @_;
+ my ($count);
+
+ push @$buff, "\n" if ($$buff[$count] ne "");
+ push @$buff, "auto " . join (" ", @ifaces) . "\n";
+}
+
+# Append a stanza for $iface to buffer.
+sub gst_replace_interfaces_iface_stanza_create
+{
+ my ($buff, $iface) = @_;
+ my ($count);
+
+ $count = $#$buff;
+ push @$buff, "\n" if ($$buff[$count] ne "");
+ push @$buff, "iface $iface inet static\n";
+}
+
+# Delete $iface stanza and all its option lines.
+sub gst_replace_interfaces_iface_stanza_delete
+{
+ my ($file, $iface) = @_;
+ my ($buff, $line_no, $line_end, $stanza);
+
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+ $line_no = 0;
+
+ return -1 if (!&gst_replace_interfaces_iface_stanza_locate ($buff, \$line_no, $iface));
+ $line_end = $line_no + 1;
+ &gst_replace_interfaces_next_stanza_locate ($buff, \$line_end);
+
+ while ($line_no < $line_end)
+ {
+ delete $$buff[$line_no];
+ $line_no++;
+ }
+
+ $line_no = 0;
+ if (&gst_replace_interfaces_auto_stanza_locate ($buff, \$line_no, $iface))
+ {
+ $line_end = $line_no + 1;
+ &gst_replace_interfaces_next_stanza_locate ($buff, \$line_end);
+
+ while ($line_no < $line_end)
+ {
+ delete $$buff[$line_no];
+ $line_no++;
+ }
+ }
+
+ &gst_file_buffer_clean ($buff);
+ return &gst_file_buffer_save ($buff, $file);
+}
+
+# Find $iface stanza line and replace $pos value (ie the method).
+sub gst_replace_interfaces_stanza_value
+{
+ my ($file, $iface, $pos, $value) = @_;
+ my ($buff, $line_no, $stanza);
+ my ($pre_space, $line, $line_arr);
+
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+ $line_no = 0;
+
+ if (!&gst_replace_interfaces_iface_stanza_locate ($buff, \$line_no, $iface))
+ {
+ $line_no = 0;
+ &gst_replace_interfaces_iface_stanza_create ($buff, $iface);
+ &gst_replace_interfaces_iface_stanza_locate ($buff, \$line_no, $iface);
+ }
+
+ $line = $$buff[$line_no];
+ chomp $line;
+ $pre_space = $1 if $line =~ s/^([ \t]+)//;
+ $line =~ s/^iface[ \t]+//;
+ @line_arr = split ("[ \t]+", $line);
+ $line_arr[$pos] = $value;
+ $$buff[$line_no] = $pre_space . "iface " . join (' ', @line_arr) . "\n";
+
+ &gst_file_buffer_clean ($buff);
+ return &gst_file_buffer_save ($buff, $file);
+}
+
+# Find/append $key option in $iface stanza and set $value.
+sub gst_replace_interfaces_option_str
+{
+ my ($file, $iface, $key, $value) = @_;
+ my ($buff, $line_no, $stanza, $ret);
+ my ($pre_space, $line, $line_arr);
+
+ &gst_report_enter ();
+ &gst_report ("replace_ifaces_str", $key, $iface);
+
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+ $line_no = 0;
+
+ if (!&gst_replace_interfaces_iface_stanza_locate ($buff, \$line_no, $iface))
+ {
+ $line_no = 0;
+ &gst_replace_interfaces_iface_stanza_create ($buff, $iface);
+ &gst_replace_interfaces_iface_stanza_locate ($buff, \$line_no, $iface);
+ }
+
+ $line_no++;
+
+ if (&gst_replace_interfaces_option_locate ($buff, \$line_no, $key))
+ {
+ if ($value eq "") # Delete option if value is empty.
+ {
+ $$buff[$line_no] = "";
+ }
+ else
+ {
+ chomp $$buff[$line_no];
+ $$buff[$line_no] =~ s/^([ \t]*$key[ \t]).*/$1/;
+ }
+ }
+ elsif ($value ne "")
+ {
+ $line_no --;
+ chomp $$buff[$line_no];
+ $$buff[$line_no] =~ s/^([ \t]*)(.*)/$1$2\n$1$key /;
+ }
+
+ $$buff[$line_no] .= $value . "\n" if $value ne "";
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+# $key option is keyword. $value says if it should exist or not.
+sub gst_replace_interfaces_option_kw
+{
+ my ($file, $iface, $key, $value) = @_;
+
+ return &gst_replace_interfaces_option_str ($file, $iface, $key, $value? " ": "");
+}
+
+# !$value says if keyword should exist or not (ie noauto).
+sub gst_replace_interfaces_option_kw_not
+{
+ my ($file, $iface, $key, $value) = @_;
+
+ return &gst_replace_interfaces_option_kw ($file, $iface, $key, !$value);
+}
+
+
+# Implementing pump(8) pump.conf file format replacer.
+# May be useful for dhcpd too.
+
+# Try to find the next option, returning an array ref
+# with the found key and the rest of the options in
+# two items, or -1 if not found.
+sub gst_replace_pump_get_next_option
+{
+ my ($buff, $line_no) = @_;
+
+ while ($$line_no < (scalar @$buff))
+ {
+ $_ = $$buff[$$line_no];
+ $_ = &gst_parse_interfaces_line_clean ($_);
+ if ($_ ne "")
+ {
+ return [ split ("[ \t]+", $_, 2) ];
+ }
+
+ $$line_no ++;
+ }
+
+ return -1;
+}
+
+# Iterate with get_next_option, starting at $line_no
+# until the option with $key is found, or eof.
+# Return 0/1 as found.
+sub gst_replace_pump_option_locate
+{
+ my ($buff, $line_no, $key) = @_;
+ my ($opt);
+
+ while (($opt = &gst_replace_pump_get_next_option ($buff, $line_no)) != -1)
+ {
+ return 1 if $$opt[0] eq $key;
+ return 0 if $$opt[0] eq "}";
+
+ $$line_no ++;
+ }
+
+ return 0;
+}
+
+# Try to find a "device" option whose interface is $iface,
+# starting at $$line_no. Return 0/1 as found.
+sub gst_replace_pump_get_device
+{
+ my ($buff, $line_no, $iface) = @_;
+ my ($opt);
+
+ while (($opt = &gst_replace_pump_get_next_option ($buff, $line_no)) != -1)
+ {
+ if ($$opt[0] eq "device")
+ {
+ $$opt[1] =~ s/[ \t]*\{//;
+ return 1 if $$opt[1] eq $iface;
+ }
+
+ $$line_no ++;
+ }
+
+ return 0;
+}
+
+# Add a device entry for $iface at the end of $buff.
+sub gst_replace_pump_add_device
+{
+ my ($buff, $iface) = @_;
+
+ push @$buff, "\n";
+ push @$buff, "device $iface {\n";
+ push @$buff, "\t\n";
+ push @$buff, "}\n";
+}
+
+# Find a "device" section for $iface and
+# replace/add/delete the $key option inside the section.
+sub gst_replace_pump_iface_option_str
+{
+ my ($file, $iface, $key, $value) = @_;
+ my ($line_no, $ret);
+
+ $buff = &gst_file_buffer_load ($file);
+ $line_no = 0;
+
+ if (!&gst_replace_pump_get_device ($buff, \$line_no, $iface))
+ {
+ $line_no = 0;
+ &gst_replace_pump_add_device ($buff, $iface);
+ &gst_replace_pump_get_device ($buff, \$line_no, $iface);
+ }
+
+ $line_no ++;
+
+ if (&gst_replace_pump_option_locate ($buff, \$line_no, $key))
+ {
+ if ($value eq "")
+ {
+ $$buff[$line_no] = "";
+ }
+ else
+ {
+ chomp $$buff[$line_no];
+ $$buff[$line_no] =~ s/^([ \t]*$key[ \t]).*/$1/;
+ }
+ }
+ elsif ($value ne "")
+ {
+ $line_no --;
+ chomp $$buff[$line_no];
+ $$buff[$line_no] =~ s/^([ \t]*)(.*)/$1$2\n$1$key /;
+ }
+
+ if ($value ne "")
+ {
+ $value =~ s/^[ \t]+//;
+ $value =~ s/[ \t]+$//;
+ $$buff[$line_no] .= &gst_parse_shell_escape ($value) . "\n";
+ }
+
+ &gst_file_buffer_clean ($buff);
+ $ret = &gst_file_buffer_save ($buff, $file);
+ &gst_report_leave ();
+ return $ret;
+}
+
+# Same as function above, except $key is a keyword.
+sub gst_replace_pump_iface_kw
+{
+ my ($file, $iface, $key, $value) = @_;
+
+ return &gst_replace_pump_iface_option_str ($file, $iface, $key, $value? " ": "");
+}
+
+# Same, but use the negative of $value (i.e. nodns)
+sub gst_replace_pump_iface_kw_not
+{
+ my ($file, $iface, $key, $value) = @_;
+
+ return &gst_replace_pump_iface_kw ($file, $iface, $key, !$value);
+}
+
+sub gst_replace_xml_pcdata
+{
+ my ($file, $varpath, $data) = @_;
+ my ($model, $branch, $fd, $compressed);
+
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_ensure ($model, $varpath);
+
+ &gst_xml_model_set_pcdata ($branch, $data);
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+sub gst_replace_xml_attribute
+{
+ my ($file, $varpath, $attr, $value) = @_;
+ my ($model, $branch, $fd, $compressed);
+
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_ensure ($model, $varpath);
+
+ &gst_xml_model_set_attribute ($branch, $attr, $value);
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+sub gst_replace_xml_pcdata_with_type
+{
+ my ($file, $varpath, $type, $data) = @_;
+ my ($model, $branch, $fd, $compressed);
+
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_ensure ($model, $varpath);
+
+ &gst_xml_model_set_pcdata ($branch, $data);
+ &gst_xml_model_set_attribute ($branch, "TYPE", $type);
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+sub gst_replace_xml_attribute_with_type
+{
+ my ($file, $varpath, $attr, $type, $value) = @_;
+ my ($model, $branch, $fd, $compressed);
+
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_ensure ($model, $varpath);
+
+ &gst_xml_model_set_attribute ($branch, $attr, $value);
+ &gst_xml_model_set_attribute ($branch, "TYPE", $type);
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+sub gst_replace_alchemist_ensure_list_types
+{
+ my ($model, $varpath, $setpath) = @_;
+ my ($branch, @path);
+
+ $branch = &gst_xml_model_find ($model, $varpath);
+ @path = split /\//, $setpath;
+
+ # NOTE: The following could be done with a depth-iterator callback from a func
+ # similar to gst_xml_model_find ().
+
+ for $elem (@path)
+ {
+ next if ($elem eq "");
+ my @children = @$branch;
+ shift @children; # Attributes
+ $branch = undef;
+
+ while (@children)
+ {
+ if ($children [0] eq $elem)
+ {
+ shift @children;
+ $branch = shift @children;
+ &gst_xml_model_set_attribute ($branch, "TYPE", "LIST");
+ last;
+ }
+
+ shift @children;
+ shift @children;
+ }
+
+ last if ($branch == undef);
+ }
+}
+
+sub gst_replace_alchemist
+{
+ my ($file, $varpath, $type, $value) = @_;
+ my ($fullpath, $model, $branch, $fd, $compressed);
+
+ $fullpath = "/adm_context/datatree/" . $varpath;
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_ensure ($model, $fullpath);
+ &gst_replace_alchemist_ensure_list_types ($model, "/adm_context/datatree/", $varpath);
+
+ &gst_xml_model_set_attribute ($branch, "VALUE", $value);
+ &gst_xml_model_set_attribute ($branch, "TYPE", $type);
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+sub gst_replace_alchemist_print
+{
+ my ($file, $printer, $varpath, $type, $value) = @_;
+ my ($fullpath, $model, $branch, $fd, $compressed);
+
+ $fullpath = "/adm_context/datatree/printconf/print_queues/" . $printer . "/" . $varpath;
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+
+ $branch = &gst_xml_model_ensure ($model, $fullpath);
+
+ &gst_replace_alchemist_ensure_list_types ($model, "/adm_context/datatree/",
+ "printconf/print_queues/" . $printer . "/" . $varpath);
+
+ &gst_xml_model_set_attribute ($branch, "VALUE", $value);
+ &gst_xml_model_set_attribute ($branch, "TYPE", $type);
+
+ $branch = &gst_xml_model_find ($model, "/adm_context/datatree/printconf/print_queues/" . $printer);
+ &gst_xml_model_set_attribute ($branch, "ATOMIC", "TRUE");
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+# This could be split up.
+sub gst_replace_alchemist_print_option
+{
+ my ($file, $printer, $name, $type, $value) = @_;
+ my ($varpath, $model, $branch, $fd, $compressed, $options, $option);
+
+ ($model, $compressed) = &gst_xml_model_scan ($file);
+ $branch = &gst_xml_model_ensure ($model, "/adm_context/datatree/printconf/print_queues/" . $printer .
+ "/filter_data/foomatic_defaults");
+ &gst_replace_alchemist_ensure_list_types ($model, "/adm_context/datatree/", "printconf/print_queues/" .
+ $printer . "/filter_data/foomatic_defaults");
+ &gst_xml_model_set_attribute ($branch, "ANONYMOUS", "TRUE");
+
+ # See if option is already defined.
+
+ $options = &gst_xml_model_get_children ($branch);
+
+ foreach $o (@$options)
+ {
+ my $opt_node = &gst_xml_model_find ($o, "name");
+ next if (!$opt_node);
+
+ if (&gst_xml_model_get_attribute ($opt_node, "VALUE") eq $name)
+ {
+ $option = $o;
+ last;
+ }
+ }
+
+ # If not, create node for it.
+
+ if (!$option)
+ {
+ $option = &gst_xml_model_add ($branch, "", $option_default);
+ &gst_xml_model_set_attribute ($option, "TYPE", "LIST");
+ }
+
+ # Set the option attributes.
+
+ my $node = &gst_xml_model_ensure ($option, "name");
+ &gst_xml_model_set_attribute ($node, "TYPE", "STRING");
+ &gst_xml_model_set_attribute ($node, "VALUE", $name);
+
+ $node = &gst_xml_model_ensure ($option, "type");
+ &gst_xml_model_set_attribute ($node, "TYPE", "STRING");
+ &gst_xml_model_set_attribute ($node, "VALUE", $type);
+
+ $node = &gst_xml_model_ensure ($option, "default");
+ &gst_xml_model_set_attribute ($node, "TYPE", "STRING");
+ &gst_xml_model_set_attribute ($node, "VALUE", $value);
+
+ return &gst_xml_model_save ($model, $file, $compressed);
+}
+
+sub gst_replace_fq_hostname
+{
+ my ($file, $hostname, $domain) = @_;
+
+ if ($domain eq undef)
+ {
+ return &gst_replace_line_first ($file, "$hostname");
+ }
+ else
+ {
+ return &gst_replace_line_first ($file, "$hostname.$domain");
+ }
+}
+
+sub gst_replace_rcinet1conf
+{
+ my ($file, $iface, $kw, $val) = @_;
+ my ($line);
+
+ $iface =~ s/eth//;
+ $line = "$kw\[$iface\]";
+
+ $val = "\"$val\"" if ($val ne undef);
+
+ return &gst_replace_split ($file, $line, "[ \t]*=[ \t]*", $val);
+}
+
+sub gst_replace_rcinet1conf_global
+{
+ my ($file, $kw, $val) = @_;
+
+ $val = "\"$val\"";
+
+ return &gst_replace_split ($file, $kw, "[ \t]*=[ \t]*", $val)
+}
+
+sub gst_replace_wireless_opts
+{
+ my ($file, $iface, $proc, $kw, $value) = @_;
+ my $ifaces = &$proc ();
+ my $found = 0;
+ my $search = 1;
+ my $buff;
+
+ foreach $i (@$ifaces)
+ {
+ $found = 1 if ($iface eq $i);
+ }
+
+ $buff = &gst_file_buffer_load ($file);
+
+ foreach $i (@$buff)
+ {
+ if (/^case/)
+ {
+ # we don't want to search inside the case
+ $search = 0;
+ }
+ elsif (/^esac/)
+ {
+ # we want to continue searching
+ $search = 1;
+ }
+ if ((/^[ \t]*$kw/) && ($search))
+ {
+ $_ = "$kw=\"$value\"";
+ $found = 1;
+ }
+ }
+
+ if (!$found)
+ {
+ push @$buff, "$kw=\"$value\"";
+ }
+
+ &gst_file_buffer_clean ($buff);
+ return &gst_file_buffer_save ($buff, $file);
+}
+
+# Functions for replacing in FreeBSD's /etc/ppp/ppp.conf
+sub gst_replace_pppconf_common
+{
+ my ($pppconf, $section, $key, $string) = @_;
+ my ($buff, $line_no, $end_line_no, $i, $found);
+
+ $buff = &gst_file_buffer_load ($pppconf);
+
+ $line_no = &gst_parse_pppconf_find_stanza ($buff, $section);
+
+ if ($line_no ne -1)
+ {
+ # The stanza exists
+ $line_no++;
+
+ $end_line_no = &gst_parse_pppconf_find_next_stanza ($buff, $line_no);
+ $end_line_no = scalar @$buff + 1 if ($end_line_no == -1);
+ $end_line_no--;
+
+ for ($i = $line_no; $i <= $end_line_no; $i++)
+ {
+ if ($$buff[$i] =~ /[ \t]+$key/)
+ {
+ if ($string ne undef)
+ {
+ $$buff[$i] = " $string\n";
+ $found = 1;
+ }
+ else
+ {
+ delete $$buff[$i];
+ }
+ }
+ }
+
+ if ($found != 1)
+ {
+ $$buff[$end_line_no] .= " $string\n" if ($string ne undef);
+ }
+ }
+ else
+ {
+ if ($string ne undef)
+ {
+ push @$buff, "$section:\n";
+ push @$buff, " $string\n";
+ }
+ }
+
+ &gst_file_buffer_clean ($buff);
+ return &gst_file_buffer_save ($buff, $pppconf);
+}
+
+sub gst_replace_pppconf
+{
+ my ($pppconf, $section, $key, $value) = @_;
+ &gst_replace_pppconf_common ($pppconf, $section, $key, "set $key $value");
+}
+
+sub gst_replace_pppconf_bool
+{
+ my ($pppconf, $section, $key, $value) = @_;
+ &gst_replace_pppconf_common ($pppconf, $section, $key,
+ ($value == 1)? "enable $key" : "disable $key");
+}
+
+sub gst_replace_confd_net_re
+{
+ my ($file, $key, $re, $value) = @_;
+ my ($str, $contents, $i, $found, $done);
+
+ $found = $done = 0;
+ $contents = &gst_file_buffer_load ($file);
+
+ for ($i = 0; $i <= scalar (@$contents); $i++)
+ {
+ # search for key
+ if ($$contents[$i] =~ /^$key[ \t]*=[ \t]*\(/)
+ {
+ $found = 1;
+
+ do {
+ if ($$contents[$i] =~ /\"([^\"]*)\"/)
+ {
+ $str = $1;
+
+ if ($str =~ /$re/)
+ {
+ $str =~ s/$re/$value/;
+ }
+ else
+ {
+ $str .= $value;
+ }
+
+ $$contents[$i] =~ s/\"([^\"]*)\"/\"$str\"/;
+ $done = 1;
+ }
+
+ $i++;
+ } while (!$done);
+ }
+ }
+
+ if (!$found)
+ {
+ push @$contents, "$key=(\"$value\")\n";
+ }
+
+ return &gst_file_buffer_save ($contents, $file);
+}
+
+sub gst_replace_confd_net
+{
+ my ($file, $key, $value) = @_;
+
+ return &gst_replace_confd_net_re ($file, $key, ".*", $value);
+}
diff --git a/knetworkconf/backends/report.pl.in b/knetworkconf/backends/report.pl.in
new file mode 100644
index 0000000..a1c23d3
--- /dev/null
+++ b/knetworkconf/backends/report.pl.in
@@ -0,0 +1,366 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# /* Functions for on-the-fly commentary on a tool's work. */
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/general.pl$DOTIN";
+
+# --- Progress printing --- #
+
+
+$gst_progress_current = 0; # Compat with old $progress_max use.
+$gst_progress_last_percentage = 0;
+
+
+sub gst_progress
+{
+ my $prc = $_[0];
+
+ # /* Don't go backwards. */
+ $prc = $gst_progress_last_percentage if ($prc < $gst_progress_last_percentage);
+
+ # /* Don't go above 99%. */
+ $prc = 99 if ($prc >= 100);
+
+ if ($gst_progress && (int $prc > int $gst_progress_last_percentage))
+ {
+ &gst_report ("progress", $prc);
+ $gst_progress_last_percentage = $prc;
+ }
+}
+
+
+sub gst_progress_begin
+{
+ &gst_progress (0);
+}
+
+
+sub gst_progress_end
+{
+ &gst_progress (99);
+}
+
+
+sub gst_print_progress # Compat with old $progress_max use.
+{
+ my $prc;
+
+ $gst_progress_current++;
+ &gst_progress (($gst_progress_current * 100) / $progress_max);
+}
+
+
+# --- Report printing --- #
+
+
+sub gst_report_begin
+{
+ my ($tool) = @_;
+
+ &gst_report ("begin");
+ &gst_report_enter ();
+ &gst_progress_begin ();
+}
+
+
+sub gst_report_end
+{
+ &gst_progress_end ();
+ &gst_report_leave ();
+ &gst_report ("end");
+}
+
+
+sub gst_report_set_threshold
+{
+ $gst_report_threshold = $_[0];
+}
+
+
+sub gst_report_enter
+{
+ # This has been trivialized because it is not working
+ # correctly at the moment and is causing some trouble.
+ # /* We'll probably replace this with something smarter */
+ # (like a detail-level value in the report hash)
+ # when the report strings are used at the gui-level again.
+# $gst_report_level ++;
+ $gst_report_level = 0;
+}
+
+
+sub gst_report_leave
+{
+# $gst_report_level --;
+ $gst_report_level = 0;
+}
+
+
+# Escapes a report using the report line format.
+sub gst_report_escape
+{
+ my ($args) = @_;
+ my ($arg);
+
+ foreach $arg (@$args)
+ {
+ $arg =~ s/\\/\\\\/g;
+ $arg =~ s/::/\\::/g;
+ }
+}
+
+
+$gst_report_level = 0;
+$gst_report_started = 0;
+
+# Just to trap these errors with the debugger easily.
+sub gst_report_stderr
+{
+ my ($major, $key, $res) = @_;
+
+ print STDERR "$gst_name - $major::${key}::$res";
+}
+
+sub gst_report
+{
+ my (@args) = @_;
+ my ($key, $major, $minor, $str, $format, $res);
+ my $report_message = &gst_report_table ();
+
+ &gst_report_escape (\@args);
+
+ $key = shift @args;
+
+ if (! (exists $$report_message{$key}))
+ {
+ &gst_report ("report_minor_unk", $key);
+ return;
+ }
+
+ ($major, $str) = @{$$report_message{$key}};
+
+ if (! (exists $gst_report_valid_majors{$major}))
+ {
+ &gst_report ("report_major_unk", $major, join ("::", $key, @args));
+ return;
+ }
+
+ $gst_report_started = 1 if !$gst_report_started && $key eq "begin" && $major eq "sys";
+
+ # Verbose (--verbose) output is human-readable only.
+ $format = "$str\n";
+ $res = sprintf ($format, @args);
+
+ if ($gst_do_verbose ||
+ $major eq "error" ||
+ $major eq "debug")
+ {
+ &gst_report_stderr ($major, $key, $res);
+ }
+
+ if ($key ne "progress")
+ {
+ return if ($gst_report_level >= $gst_report_threshold || !$gst_report_started);
+ }
+
+ # Report (--report) output is machine-readable.
+ if ($gst_do_report)
+ {
+ print STDOUT join ("::", $major, $key, $str, @args) . "\n";
+ }
+
+ &gst_debug_print_indented_string ($gst_report_level, "report $major:$key: $res");
+}
+
+# Internal
+{
+ my $report_table = \%gst_report_message;
+ sub gst_report_table
+ {
+ my $table = shift @_;
+
+ if ($table) # Add
+ {
+ foreach my $key (keys %$table)
+ {
+ $$report_table{$key} = $$table{$key} unless exists $$report_table{$key};
+ }
+ }
+
+ else # Get
+ {
+ return $report_table;
+ }
+ }
+}
+
+# This disables reporting.
+&gst_report_set_threshold (0);
+
+%gst_report_valid_majors = (
+ "sys" => 1,
+ "error" => 1,
+ "warn" => 1,
+ "info" => 1,
+ "debug" => 1
+ );
+
+%gst_report_message =
+ (
+ "begin" => ["sys", "Start of work report."],
+ "end" => ["sys", "End of work report."],
+ "progress" => ["sys", "%d"],
+ "compat" => ["info", "%s."],
+
+ "report_major_unk" => ["error", "Unknown major [%s] in report [%s]."],
+ "report_minor_unk" => ["error", "Unknown minor [%s]."],
+
+ "directive_run" => ["info", "Running directive [%s] with args [%s]."],
+ "directive_unsup" => ["error", "Directive [%s] not supported."],
+ "directive_invalid" => ["error", "Directive [%s] structure has wrong format."],
+ "directive_badargs" => ["error", "Directive [%s] requires exactly [%s] args in [%s]."],
+ "directive_lowargs" => ["error", "Directive [%s] requires at least [%s] args in [%s]."],
+
+ "platform_unsup" => ["error", "Your platform [%s] is not supported."],
+ "platform_undet" => ["error", "Unable to determine host platform."],
+ "platform_success" => ["sys", "Configuring for platform [%s] (%s)."],
+ "platform_no_table" => ["error", "No parse/replace table for platform [%s]."],
+
+ "xml_unexp_tag" => ["error", "Unexpected tag [%s]."],
+ "xml_unexp_arg" => ["error", "Unexpected argument [%s] to tag [%s]."],
+
+ "file_copy_failed" => ["debug", "Could not copy file [%s] to [%s]."],
+ "file_open_read_failed" => ["warn", "Could not open [%s] for reading."],
+ "file_open_read_success" => ["info", "Reading options from [%s]."],
+ "file_open_write_failed" => ["error", "Failed to write to [%s]."],
+ "file_open_write_create" => ["warn", "Could not find [%s] for writing. Creating [%s]."],
+ "file_open_write_success" => ["info", "Writing to [%s]."],
+ "file_run_pipe_failed" => ["warn", "Failed to pipe command [%s] for reading."],
+ "file_run_pipe_success" => ["info", "Piping command [%s] for reading."],
+ "file_run" => ["info", "Running command [%s]."],
+ "file_create_path" => ["info", "Directory [%s] created."],
+ "file_backup_rotate" => ["info", "Backup directory [%s] was rotated."],
+ "file_backup_success" => ["info", "Saved backup for [%s]."],
+ "file_open_filter_failed" => ["warn", "No file to patch: [%s]."],
+ "file_open_filter_create" => ["warn", "Could not find [%s] for patching. Creating [%s]."],
+ "file_open_filter_success" => ["info", "Found [%s]. Patching [%s]."],
+ "file_buffer_load" => ["info", "Loading file [%s] to buffer."],
+ "file_buffer_save" => ["info", "Saving buffer to file [%s]."],
+ "file_remove" => ["info", "Removing file [%s]."],
+ "file_locate_tool_success" => ["info", "Found tool [%s]."],
+ "file_locate_tool_failed" => ["warn", "Couldn't find tool [%s]."],
+
+ "parse_table" => ["info", "Parsing option [%s]."],
+ "parse_trivial" => ["info", "Trivialy passing [%s]."],
+ "parse_split" => ["info", "Getting option [%s] from [%s]."],
+ "parse_split_hash" => ["info", "Getting configuration from [%s]."],
+ "parse_split_hash_cont" => ["info", "Getting configuration from [%s]."],
+ "parse_sh" => ["info", "Getting shell option [%s] from [%s]."],
+ "parse_kw" => ["info", "Getting keyword [%s] from [%s]."],
+ "parse_line_first" => ["info", "Getting information from [%s]."],
+ "parse_chat" => ["info", "Getting chat information from [%s]."],
+ "parse_ini" => ["info", "Getting option [%s] from [%s], section [%s]."],
+ "parse_ifaces_str" => ["info", "Getting option [%s] from interface [%s]."],
+ "parse_ifaces_kw" => ["info", "Getting keyword [%s] from interface [%s]."],
+ "parse_ifaces_kw_strange" => ["warn", "Keyword for interface [%s] in [%s] had unexpected value."],
+
+ "replace_split" => ["info", "Replacing key [%s] in [%s]."],
+ "replace_sh" => ["info", "Replacing shell var [%s] in [%s]."],
+ "replace_kw" => ["info", "Replacing keyword [%s] in [%s]."],
+ "replace_line_first" => ["info", "Replacing contents of file [%s]."],
+ "replace_chat" => ["info", "Replacing values in [%s]."],
+ "replace_ini" => ["info", "Replacing variable [%s] in section [%s] of [%s]."],
+ "replace_del_ini_sect" => ["info", "Removing section [%s] from [%s]."],
+ "replace_ifaces_str" => ["info", "Replacing option [%s] from interface [%s]."],
+ "replace_ifaces_kw" => ["info", "Replacing keyword [%s] from interface [%s]."],
+
+ "service_status_running" => ["info", "Service [%s] is running."],
+ "service_status_stopped" => ["info", "Service [%s] is stopped."],
+ "service_sysv_unsupported" => ["info", "No SystemV support for platform [%s]."],
+ "service_sysv_not_found" => ["warn", "Could not find SystemV scripts for service [%s]."],
+ "service_sysv_no_runlevel" => ["warn", "Could not find SystemV runlevel [%s] directory [%s]."],
+ "service_sysv_remove_link" => ["info", "Removed SystemV link [%s]."],
+ "service_sysv_add_link" => ["info", "Created SystemV link [%s]."],
+ "service_sysv_op_unk" => ["error", "Unknown initd operation [%s]."],
+ "service_sysv_op_success" => ["info", "Service [%s] %s."],
+ "service_sysv_op_failed" => ["warn", "Service [%s] could not be %s."],
+
+ "network_dialing_get" => ["info", "Loading ISP configurations."],
+ "network_iface_active_get" => ["info", "Finding active interfaces."],
+ "network_iface_is_active" => ["info", "Checking if interface [%s] is active."],
+ "network_hostname_set" => ["info", "Setting hostname to [%s]."],
+ "network_dialing_set" => ["info", "Saving ISP configurations."],
+ "network_remove_pap" => ["info", "Removing entry [%s] from [%s]."],
+ "network_iface_set" => ["info", "Configuring interface [%s]."],
+ "network_iface_activate" => ["info", "Activating interface [%s]."],
+ "network_iface_deactivate" => ["info", "Deactivating interface [%s]."],
+ "network_ifaces_set" => ["info", "Setting up interfaces."],
+ "network_get_pap_passwd" => ["info", "Getting PAP/CHAP password for [%s] from [%s]."],
+ "network_get_ppp_option" => ["info", "Getting option [%s] from [%s]."],
+ "network_set_ppp_option" => ["info", "Setting option [%s] in [%s]."],
+ "network_set_ppp_connect" => ["info", "Setting connect option in [%s]."],
+ "network_get_ppp_unsup" => ["info", "Getting additional options from [%s]."],
+ "network_set_ppp_unsup" => ["info", "Setting additional options in [%s]."],
+ "network_bootproto_unsup" => ["warn", "Boot method [%s] for interface [%s] not supported."],
+ "network_get_remote" => ["info", "Getting remote address for interface [%s]."],
+ "network_set_remote" => ["info", "Setting remote address for interface [%s]."],
+ "network_ensure_lo" => ["info", "Ensuring loopback interface configuration."],
+
+ "filesys_mount" => ["info", "Mounting [%s] on [%s]."],
+ "filesys_mount_failed" => ["warn", "Failed to mount [%s] on [%s]."],
+ "filesys_unmount" => ["info", "Unmounting [%s] from [%s]."],
+ "filesys_unmount_failed" => ["warn", "Failed to unmount [%s] from [%s]."],
+
+ "boot_lilo_failed" => ["warn", "Failed to run lilo."],
+ "boot_lilo_success" => ["info", "Succesfully executed lilo."],
+ "boot_conf_read_failed" => ["error", "Failed to open boot configuration file [%s]."],
+ "boot_grub_convert_failed" => ["error", "Conversion of [%s] failed."],
+
+ "sfdisk_failed" => ["error", "Could not run sfdisk."],
+
+ "disks_fstab_add" => ["info", "Adding [%s] to fstab."],
+ "disks_partition_probe" => ["info", "Looking for partitions on [%s]."],
+ "disks_size_query" => ["info", "Querying size of [%s]."],
+ "disks_mount" => ["info", "Mounting [%s]."],
+ "disks_umount" => ["info", "Unmounting [%s]."],
+ "disks_mount_error" => ["error", "Could not find mount tools. No mounting done."],
+
+ "memory_swap_found" => ["info", "Found swap entry [%s]."],
+ "memory_swap_probe" => ["info", "Looking for swap entries."],
+
+ "print_no_printtool" => ["warn", "No printtool setup in directory [%s]."],
+
+ "time_timezone_scan" => ["info", "Scanning timezones."],
+ "time_timezone_cmp" => ["info", "Scanning timezones: [%s]."],
+ "time_timezone_set" => ["info", "Setting timezone as [%s]."],
+ "time_localtime_set" => ["info", "Setting local time as [%s]."]
+ );
+
+1;
diff --git a/knetworkconf/backends/service-list.pl.in b/knetworkconf/backends/service-list.pl.in
new file mode 100644
index 0000000..460c4ea
--- /dev/null
+++ b/knetworkconf/backends/service-list.pl.in
@@ -0,0 +1,337 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Functions for getting service descriptions.
+#
+# Copyright (C) 2002 Ximian, Inc.
+#
+# Authors: Carlos Garnacho Parro <garnacho@tuxerver.net>
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+# This function determines if a service is "forbidden" or not (if runlevel-admin must show it or not)
+sub gst_service_list_service_is_forbidden
+{
+ my ($service) = @_;
+ my ($ret);
+
+ my ($service_forbidden_list) =
+ [
+ # These are the forbidden services I found in Red Hat
+ "halt",
+ "functions",
+ "killall",
+ # These are the forbidden services I found in Debian Woody
+ "single",
+ "sendsigs",
+ "reboot",
+ "rcS",
+ "modutils",
+ "hostname\.sh",
+ "devpts\.sh",
+ "console-screen\.sh",
+ "checkroot\.sh",
+ "checkfs\.sh",
+ "bootmisc\.sh",
+ "bootclean\.sh",
+ "checkfs\.sh",
+ "keymap\.sh",
+ "hwclockfirst\.sh",
+ "etc-setserial",
+ "procps\.sh",
+ "mountall\.sh",
+ "dns-clean",
+ "ifupdown",
+ "networking",
+ "mountnfs\.sh",
+ "mountkernfs",
+ "mountvirtfs",
+ "setserial",
+ "hwclock\.sh",
+ "urandom",
+ "nviboot",
+ "pppd-dns",
+ "skeleton",
+ "xfree86-common",
+ "rc",
+ ".*\.dpkg-old",
+ ".*~",
+ # this shouldn't be shown in slackware
+ "inet2",
+ # those were found in gentoo
+ "bootmisc",
+ "checkfs",
+ "checkroot",
+ "clock",
+ "consolefont",
+ "crypto-loop",
+ "domainname",
+ "hostname",
+ "keymaps",
+ "localmount",
+ "net\..*",
+ "numlock",
+ "depscan\.sh",
+ "functions\.sh",
+ "halt\.sh",
+ "reboot\.sh",
+ "rmnologin",
+ "runscript\.sh",
+ "serial",
+ "shutdown\.sh",
+ "switch",
+ # those were found in FreeBSD
+ "DAEMON",
+ "LOGIN",
+ "NETWORKING",
+ "SERVERS",
+ "addswap",
+ "adjkerntz",
+ "archdep",
+ "atm2\.sh",
+ "atm3\.sh",
+ "ccd",
+ "cleanvar",
+ "devdb",
+ "devfs",
+ "dhclient",
+ "diskless",
+ "dumpon",
+ "fsck",
+ "hostname",
+ "initdiskless",
+ "initrandom",
+ "ldconfig",
+ "local",
+ "localdaemons",
+ "mountcritlocal",
+ "mountcritremote",
+ "msgs",
+ "netif",
+ "network1",
+ "network2",
+ "network3",
+ "nisdomain",
+ "othermta",
+ "pccard",
+ "pcvt",
+ "pwcheck",
+ "random",
+ "rcconf\.sh",
+ "root",
+ "savecore",
+ "securelevel",
+ "serial",
+ "sppp",
+ "swap1",
+ "syscons",
+ "sysctl",
+ "ttys",
+ "virecover",
+ # These are the services found in SuSE
+ "rc[sS0-9]\.d",
+ "boot",
+ "boot\..*",
+ ];
+
+ foreach $i (@$service_forbidden_list)
+ {
+ return 1 if ($service =~ "^$i\$");
+ }
+
+ return undef;
+}
+
+
+# Ok, maybe we should define this roles stuff a bit:
+#
+# SYSTEM: all system related services that only powerusers care of
+# SOUND: any service related to sound
+# WEB_SERVER: any web server
+# COMMAND_SCHEDULER: any service which runs scheduled commands
+# NETWORK: network related services that only powerusers care of
+# PRINTER_SERVICE: printing daemons in general
+# DYNAMIC_DNS: Dinamic DNS services
+# DICT:
+# MTA: Mail transport agents
+# MAIL_FETCHER: services that fetch the mail from other accounts
+# DISPLAY_MANAGER: Display managers
+# SYSTEM_LOGGER: system log services
+# DATABASE_SERVER: database servers
+# FILE_SERVER: file servers
+# NTP_SERVER: Network time protocol servers
+# SECURE_SHELL_SERVER: Secure shell servers
+# AUTOMOUNTER: automounter daemons and so
+# ANTIVIRUS:
+# FILE_SHARING: for emule-like services
+# FTP_SERVER:
+#
+#
+# If you feel that there are more important/necessary roles,
+# mail me at carlosg@gnome.org
+
+sub gst_service_get_role
+{
+ my ($script) = @_;
+
+ my %service_roles = (
+ "acpid" => "SYSTEM",
+ "alsa" => "SOUND",
+ "am-utils" => "AUTOMOUNTER",
+ "amavis" => "ANTIVIRUS",
+ "amavis-ng" => "ANTIVIRUS",
+ "apache" => "WEB_SERVER",
+ "apache-perl" => "WEB_SERVER",
+ "apache-ssl" => "WEB_SERVER",
+ "apache2" => "WEB_SERVER",
+ "anacron" => "COMMAND_SCHEDULER",
+ "apmd" => "SYSTEM",
+ "atd" => "COMMAND_SCHEDULER", #FIXME
+ "atftpd" => "FTP_SERVER",
+ "aumix" => "SOUND",
+ "autofs" => "AUTOMOUNTER",
+ "bind" => "NETWORK",
+ "binfmt-support" => "SYSTEM",
+ "bootlogd" => "SYSTEM",
+ "chargen" => "NETWORK",
+ "chargen-udp" => "NETWORK",
+ "cherokee" => "WEB_SERVER",
+ "clamav-daemon" => "ANTIVIRUS",
+ "courier" => "MTA",
+ "courier-mta" => "MTA",
+ "cpufreqd" => "SYSTEM",
+ "cron" => "COMMAND_SCHEDULER",
+ "crond" => "COMMAND_SCHEDULER",
+ "cupsd" => "PRINTER_SERVICE",
+ "cups" => "PRINTER_SERVICE",
+ "cupsys" => "PRINTER_SERVICE",
+ "daytime" => "NETWORK",
+ "daytime-udp" => "NETWORK",
+ "dbus-1" => "SYSTEM",
+ "ddclient" => "DYNAMIC_DNS",
+ "dhis-client" => "DYNAMIC_DNS",
+ "dictd" => "DICT",
+ "echo" => "NETWORK",
+ "echo-udp" => "NETWORK",
+ "esound" => "SOUND",
+ "exim" => "MTA",
+ "fam" => "SYSTEM",
+ "fcron" => "COMMAND_SCHEDULER",
+ "firstboot" => "SYSTEM",
+ "festival" => "SOUND", #FIXME
+ "fetchmail" => "MAIL_FETCHER",
+ "freenet6" => "NETWORK",
+ "ftpd" => "FTP_SERVER",
+ "gdm" => "DISPLAY_MANAGER",
+ "gpm" => "SYSTEM", #FIXME
+ "hdparm" => "SYSTEM",
+ "hotplug" => "SYSTEM",
+ "httpd" => "WEB_SERVER",
+ "inetd" => "NETWORK",
+ "iptables" => "NETWORK",
+ "irda" => "SYSTEM",
+ "isakmpd" => "NETWORK",
+ "isdn" => "NETWORK",
+ "joystick" => "SYSTEM",
+ "kdm" => "DISPLAY_MANAGER",
+ "keytable" => "SYSTEM",
+ "klogd" => "SYSTEM_LOGGER",
+ "kudzu" => "SYSTEM",
+ "lircd" => "SYSTEM",
+ "lircmd" => "SYSTEM",
+ "local" => "SYSTEM",
+ "lpd" => "PRINTER_SERVICE",
+ "lpdng" => "PRINTER_SERVICE",
+ "mailscanner" => "ANTIVIRUS",
+ "makedev" => "SYSTEM",
+ "metalog" => "SYSTEM_LOGGER",
+ "mldonkey-server" => "FILE_SHARING",
+ "modules" => "SYSTEM",
+ "module-init-tools" => "SYSTEM",
+ "mysql" => "DATABASE_SERVER",
+ "muddleftpd" => "FTP_SERVER",
+ "named" => "NETWORK",
+ "netfs" => "SYSTEM",
+ "network" => "SYSTEM",
+ "nfs" => "FILE_SERVER",
+ "nfs-user-server" => "FILE_SERVER",
+ "nfs-kernel-server" => "FILE_SERVER",
+ "nfslock" => "SYSTEM",
+ "nscd" => "NETWORK",
+ "ntpd" => "NTP_SERVER",
+ "ntpdate" => "NTP_SERVER",
+ "ntp-client" => "NTP_CLIENT",
+ "ntp-simple" => "NTP_SERVER",
+ "oftpd" => "FTP_SERVER",
+ "oops" => "NETWORK",
+ "pcmcia" => "SYSTEM",
+ "pdnsd" => "NETWORK",
+ "pipsecd" => "NETWORK",
+ "portmap" => "NETWORK",
+ "postfix" => "MTA",
+ "postgresql" => "DATABASE_SERVER",
+ "postgresql-7.4" => "DATABASE_SERVER",
+ "postgresql-8.0" => "DATABASE_SERVER",
+ "ppp" => "NETWORK",
+ "proftpd" => "FTP_SERVER",
+ "privoxy" => "NETWORK",
+ "pure-ftpd" => "FTP_SERVER",
+ "qmail" => "MTA",
+ "random" => "SYSTEM",
+ "rawdevices" => "SYSTEM",
+ "rhnsd" => "SYSTEM",
+ "rsync" => "NETWORK",
+ "rsyncd" => "NETWORK",
+ "samba" => "FILE_SERVER",
+ "saslauthd" => "SYSTEM", # FIXME: maybe a SECURITY role makes sense?
+ "sendmail" => "MTA",
+ "servers" => "NETWORK",
+ "services" => "NETWORK",
+ "setserial" => "SYSTEM",
+ "sgi_fam" => "SYSTEM",
+ "smartmontools" => "SYSTEM",
+ "spamassassin" => "SYSTEM",
+ "snmpd" => "NETWORK",
+ "ssh" => "SECURE_SHELL_SERVER",
+ "sshd" => "SECURE_SHELL_SERVER",
+ "sysklogd" => "SYSTEM_LOGGER",
+ "syslog" => "SYSTEM_LOGGER",
+ "tftpd-hpa" => "FTP_SERVER",
+ "time" => "NETWORK",
+ "time-udp" => "NETWORK",
+ "urandom" => "SYSTEM",
+ "vcron" => "COMMAND_SCHEDULER",
+ "vmware" => "SYSTEM", # FIXME
+ "vsftpd" => "FTP_SERVER",
+ "wdm" => "DISPLAY_MANAGER",
+ "webmin" => "SYSTEM", # FIXME as well
+ "winbind" => "NETWORK",
+ "wine" => "SYSTEM", # FIXME like vmware
+ "wu-ftpd" => "FTP_SERVER",
+ "wzdftpd" => "FTP_SERVER",
+ "xdm" => "DISPLAY_MANAGER",
+ "xfs" => "SYSTEM",
+ "xinetd" => "NETWORK",
+ "zmailer" => "MTA",
+ );
+
+ my ($role) = $service_roles{$script};
+
+ return $role if ($role);
+ return "UNKNOWN";
+}
+
+1;
diff --git a/knetworkconf/backends/service.pl.in b/knetworkconf/backends/service.pl.in
new file mode 100644
index 0000000..d4ce8b3
--- /dev/null
+++ b/knetworkconf/backends/service.pl.in
@@ -0,0 +1,2119 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Functions for manipulating system services, like daemons and network.
+#
+# Copyright (C) 2002 Ximian, Inc.
+#
+# Authors: Carlos Garnacho Parro <garparr@teleline.es>,
+# Hans Petter Jansson <hpj@ximian.com>,
+# Arturo Espinosa <arturo@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+$rcd_path;
+$initd_path;
+$relative_path;
+
+$SCRIPTSDIR = "@scriptsdir@";
+$FILESDIR = "@filesdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $FILESDIR = "files";
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+use File::Copy;
+
+require "$SCRIPTSDIR/file.pl$DOTIN";
+require "$SCRIPTSDIR/report.pl$DOTIN";
+require "$SCRIPTSDIR/service-list.pl$DOTIN";
+
+# Where is the SysV subsystem installed?
+sub gst_service_sysv_get_paths
+{
+ my %dist_map =
+ (
+ # gst_dist => [rc.X dirs location, init.d scripts location, relative path location]
+ "redhat-5.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-6.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-6.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-6.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-7.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-7.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-7.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-7.3" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-8.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "redhat-9" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "openna-1.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "mandrake-7.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-7.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-9.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-9.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-9.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-10.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-10.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandrake-10.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandriva-2006.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandriva-2006.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandriva-2007.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "mandriva-2007.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "yoper-2.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "blackpanther-4.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "conectiva-9" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "conectiva-10" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "debian-2.2" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "debian-3.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "debian-3.1" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "debian-4.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "debian-5.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "debian-testing" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-5.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-5.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-6.06" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-6.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-7.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-7.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+ "ubuntu-8.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"],
+
+ "suse-7.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d", "../"],
+ "suse-9.0" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"],
+ "suse-9.1" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"],
+
+ "turbolinux-7.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "pld-1.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "pld-1.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "pld-1.99" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "fedora-1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "fedora-2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "fedora-3" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "fedora-4" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "fedora-5" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "rpath" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+
+ "vine-3.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "vine-3.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ "ark" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
+ );
+ my $res;
+
+ $res = $dist_map{$gst_dist};
+ &gst_report ("service_sysv_unsupported", $gst_dist) if ($res eq undef);
+ return @$res;
+}
+
+# Those runlevels that are usually used. Maybe we should add
+# the current running runlevel, using the "runlevel" command.
+sub gst_service_sysv_get_runlevels
+{
+ my %dist_map =
+ (
+ "redhat-5.2" => [3, 5],
+ "redhat-6.0" => [3, 5],
+ "redhat-6.1" => [3, 5],
+ "redhat-6.2" => [3, 5],
+ "redhat-7.0" => [3, 5],
+ "redhat-7.1" => [3, 5],
+ "redhat-7.2" => [3, 5],
+ "redhat-7.3" => [3, 5],
+ "redhat-8.0" => [3, 5],
+ "redhat-9" => [3, 5],
+ "openna-1.0" => [3, 5],
+
+ "mandrake-7.1" => [3, 5],
+ "mandrake-7.2" => [3, 5],
+ "mandrake-9.0" => [3, 5],
+ "mandrake-9.1" => [3, 5],
+ "mandrake-9.2" => [3, 5],
+ "mandrake-10.0" => [3, 5],
+ "mandrake-10.1" => [3, 5],
+ "mandrake-10.2" => [3, 5],
+ "mandriva-2006.0" => [3, 5],
+ "mandriva-2006.1" => [3, 5],
+ "mandriva-2007.0" => [3, 5],
+ "mandriva-2007.1" => [3, 5],
+
+ "yoper-2.2" => [3, 5],
+
+ "blackpanther-4.0" => [3, 5],
+
+ "conectiva-9" => [3, 5],
+ "conectiva-10" => [3, 5],
+
+ "debian-2.2" => [2, 3],
+ "debian-3.0" => [2, 3],
+ "debian-3.1" => [2, 3],
+ "debian-4.0" => [2, 3],
+ "debian-5.0" => [2, 3],
+ "debian-testing" => [2, 3],
+ "ubuntu-5.04" => [2, 3],
+ "ubuntu-5.10" => [2, 3],
+ "ubuntu-6.06" => [2, 3],
+ "ubuntu-6.10" => [2, 3],
+ "ubuntu-7.04" => [2, 3],
+ "ubuntu-7.10" => [2, 3],
+ "ubuntu-8.04" => [2, 3],
+
+ "suse-7.0" => [3, 5],
+ "suse-9.0" => [3, 5],
+ "suse-9.1" => [3, 5],
+
+ "turbolinux-7.0" => [3, 5],
+
+ "pld-1.0" => [3, 5],
+ "pld-1.1" => [3, 5],
+ "pld-1.99" => [3, 5],
+
+ "fedora-1" => [3, 5],
+ "fedora-2" => [3, 5],
+ "fedora-3" => [3, 5],
+ "fedora-4" => [3, 5],
+ "fedora-5" => [3, 5],
+ "rpath" => [3, 5],
+
+ "vine-3.0" => [3, 5],
+ "vine-3.1" => [3, 5],
+ "ark" => [3, 5],
+ );
+ my $res;
+
+ $res = $dist_map{$gst_dist};
+ &gst_report ("service_sysv_unsupported", $gst_dist) if ($res eq undef);
+ return @$res;
+}
+
+sub gst_service_get_runlevel_roles
+{
+ my (%dist_map, %runlevels, $desc, $distro);
+ %dist_map =
+ (
+ "redhat-5.2" => "redhat-5.2",
+ "redhat-6.0" => "redhat-5.2",
+ "redhat-6.1" => "redhat-5.2",
+ "redhat-6.2" => "redhat-5.2",
+ "redhat-7.0" => "redhat-5.2",
+ "redhat-7.1" => "redhat-5.2",
+ "redhat-7.2" => "redhat-5.2",
+ "redhat-7.3" => "redhat-5.2",
+ "redhat-8.0" => "redhat-5.2",
+ "redhat-9" => "redhat-5.2",
+ "openna-1.0" => "redhat-5.2",
+
+ "mandrake-7.1" => "redhat-5.2",
+ "mandrake-7.2" => "redhat-5.2",
+ "mandrake-9.0" => "redhat-5.2",
+ "mandrake-9.1" => "redhat-5.2",
+ "mandrake-9.2" => "redhat-5.2",
+ "mandrake-10.0" => "redhat-5.2",
+ "mandrake-10.1" => "redhat-5.2",
+ "mandrake-10.2" => "redhat-5.2",
+ "mandriva-2006.0" => "redhat-5.2",
+ "mandriva-2006.1" => "redhat-5.2",
+ "mandriva-2007.0" => "redhat-5.2",
+ "mandriva-2007.1" => "redhat-5.2",
+
+ "yoper-2.2" => "redhat-5.2",
+
+ "blackpanther-4.0" => "redhat-5.2",
+
+ "conectiva-9" => "redhat-5.2",
+ "conectiva-10" => "redhat-5.2",
+
+ "debian-2.2" => "debian-2.2",
+ "debian-3.0" => "debian-2.2",
+ "debian-3.1" => "debian-2.2",
+ "debian-4.0" => "debian-2.2",
+ "debian-5.0" => "debian-2.2",
+ "debian-testing" => "debian-2.2",
+ "ubuntu-5.04" => "debian-2.2",
+ "ubuntu-5.10" => "debian-2.2",
+ "ubuntu-6.06" => "debian-2.2",
+ "ubuntu-6.10" => "debian-2.2",
+ "ubuntu-7.04" => "debian-2.2",
+ "ubuntu-7.10" => "debian-2.2",
+ "ubuntu-8.04" => "debian-2.2",
+
+ "suse-7.0" => "redhat-5.2",
+ "suse-9.0" => "redhat-5.2",
+ "suse-9.1" => "redhat-5.2",
+
+ "turbolinux-7.0" => "redhat-5.2",
+ "pld-1.0" => "redhat-5.2",
+ "pld-1.1" => "redhat-5.2",
+ "pld-1.99" => "redhat-5.2",
+ "fedora-1" => "redhat-5.2",
+ "fedora-2" => "redhat-5.2",
+ "fedora-3" => "redhat-5.2",
+ "fedora-4" => "redhat-5.2",
+ "fedora-5" => "redhat-5.2",
+ "rpath" => "redhat-5.2",
+
+ "vine-3.0" => "redhat-5.2",
+ "vine-3.1" => "redhat-5.2",
+ "ark" => "redhat-5.2",
+
+ "slackware-9.1.0" => "slackware-9.1.0",
+ "slackware-10.0.0" => "slackware-9.1.0",
+ "slackware-10.1.0" => "slackware-9.1.0",
+ "slackware-10.2.0" => "slackware-9.1.0",
+
+ "gentoo" => "gentoo",
+ "vlos-1.2" => "gentoo",
+
+ "archlinux" => "freebsd-5",
+ "freebsd-5" => "freebsd-5",
+ "freebsd-6" => "freebsd-5",
+ );
+
+ %runlevels=
+ (
+ "redhat-5.2" => {"0" => "HALT",
+ "1" => "RECOVER",
+ "2" => "NONE",
+ "3" => "TEXT",
+ "4" => "NONE",
+ "5" => "GRAPHICAL",
+ "6" => "REBOOT"
+ },
+ "debian-2.2" => {"0" => "HALT",
+ "1" => "RECOVER",
+ "2" => "NONE",
+ "3" => "NONE",
+ "4" => "NONE",
+ "5" => "NONE",
+ "6" => "REBOOT"
+ },
+ "gentoo" => {"boot" => "BOOT",
+ "default" => "GRAPHICAL",
+ "nonetwork" => "RECOVER"
+ },
+ "freebsd-5" => {"rc" => "GRAPHICAL" },
+ "slackware-9.1.0" => {"4" => "GRAPHICAL" }
+ );
+
+ $distro = $dist_map{$gst_dist};
+ $desc = $runlevels{$distro};
+
+ return $runlevels{$distro};
+}
+
+# --- Plain process utilities --- #
+
+# Get owners list (login) of named process.
+sub gst_service_proc_get_owners
+{
+ my ($service) = @_;
+ my ($user, $pid, $command);
+ my ($fd);
+ my (@arr);
+
+ &gst_report_enter ();
+
+ $fd = gst_file_run_pipe_read ("ps acx -o user,pid,command");
+
+ while (<$fd>)
+ {
+ /(.*)[ \t]+(.*)[ \t]+(.*)/;
+ $user = $1;
+ $pid = $2;
+ $command = $3;
+
+ push @arr, $user if ($command eq $service);
+ }
+
+ &gst_report_leave ();
+ return \@arr;
+}
+
+# Stops all instances of a process
+sub gst_service_proc_stop_all
+{
+ my ($service) = @_;
+
+ return &gst_file_run ("killall $service");
+}
+
+# Starts instances of a process for a given list of users
+sub gst_service_proc_start_all
+{
+ my ($cmd, $users) = @_;
+ my ($fqcmd, $fqsu);
+
+ $fqcmd = &gst_file_get_cmd_path ($cmd);
+ $fqsu = &gst_file_locate_tool ("su");
+
+ foreach $user (@$users)
+ {
+ # Can't use gst_file_run_bg here, since it clobbers the quotes.
+ system ("$fqsu $user -c \"$fqcmd &\" >/dev/null 2>/dev/null");
+ }
+}
+
+sub gst_service_sysv_list_dir
+{
+ my ($path) = @_;
+ my ($service, @services);
+
+ foreach $service (<$path/*>)
+ {
+ if (-x $service)
+ {
+ $service =~ s/.*\///;
+ push @services, $service;
+ }
+ }
+
+ return \@services;
+}
+
+sub gst_service_sysv_list_available
+{
+ my ($rcd_path, $initd_path);
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ return &gst_service_sysv_list_dir ($initd_path);
+}
+
+# Return 1 or 0: is the service running?
+# Depends on the rc script to support the "status" arg.
+# Maybe we should do something more portable.
+sub gst_service_sysv_get_status
+{
+ my ($service) = @_;
+ my ($rc_path, $initd_path, $res);
+ my ($pid);
+
+ &gst_report_enter ();
+
+ # Stolen from RedHat's /etc/rc.d/init.d/functions:status
+ # FIXME: portable to other UNIXES?
+ $pid = &gst_file_run_backtick ("pidof -o %PPID -x $service");
+ chomp $pid;
+
+ if ($pid)
+ {
+ $res = 1;
+ &gst_report ("service_status_running", $service);
+ }
+ else
+ {
+ $res = 0;
+ &gst_report ("service_status_stopped", $service);
+ }
+
+# ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+# $res = 0;
+#
+# if (-f "$initd_path/$service")
+# {
+# $res = &gst_file_run ("$initd_path/$service status")? 0 : 1;
+# &gst_report ("service_status_running", $service) if $res;
+# &gst_report ("service_status_stopped", $service) if !$res;
+# }
+
+ &gst_report_leave ();
+ return $res;
+}
+
+# If any of the passed services is running, return true.
+sub gst_service_sysv_get_status_any
+{
+ my (@services) = @_;
+ my $i;
+
+ foreach $i (@services)
+ {
+ return 1 if &gst_service_sysv_get_status ($i);
+ }
+
+ return 0;
+}
+
+# Set start links and remove stop links at the usual runlevels.
+# Old start link is removed, in case the priority is different from $pri.
+sub gst_service_sysv_set_links_active
+{
+ my ($pri, $service) = @_;
+
+ foreach $runlevel (&gst_service_sysv_get_runlevels ())
+ {
+ &gst_service_sysv_remove_link ($runlevel, $service);
+ &gst_service_sysv_add_link ($runlevel, "S", $pri, $service);
+ }
+}
+
+# Set stop links and remove start links at the usual runlevels.
+sub gst_service_sysv_set_links_inactive
+{
+ my ($pri, $service) = @_;
+
+ foreach $runlevel (&gst_service_sysv_get_runlevels ())
+ {
+ &gst_service_sysv_remove_link ($runlevel, "$service");
+ &gst_service_sysv_add_link ($runlevel, "K", $pri, $service);
+ }
+}
+
+# Set links for active/inactive service at the given priority.
+sub gst_service_sysv_set_links
+{
+ my ($pri, $service, $active) = @_;
+
+ if ($active)
+ {
+ &gst_service_sysv_set_links_active ($pri, $service);
+ }
+ else
+ {
+ &gst_service_sysv_set_links_inactive (100 - $pri, $service);
+ }
+}
+
+
+
+# Start or stop the service, depending on $active. Set
+# links accordingly. $force makes this function use
+# start/stop only, without considerations for restart.
+# Not to be called from parse/replace tables, due to last $force
+# param: use the following two functions instead.
+sub gst_service_sysv_set_status_do
+{
+ my ($priority, $service, $active, $force) = @_;
+ my ($arg, $status);
+
+ &gst_service_sysv_set_links ($priority, $service, $active);
+
+ $status = &gst_service_sysv_get_status ($service);
+ if ($status && !$force)
+ {
+ # if it's already active and you want it active, restart.
+ $arg = $active? "restart" : "stop";
+ }
+ else
+ {
+ # normal operation.
+ $arg = $active? "start" : "stop";
+ }
+
+ return &gst_service_sysv_run_initd_script ($service, $arg);
+}
+
+sub gst_service_sysv_set_status
+{
+ my ($priority, $service, $active) = @_;
+
+ return &gst_service_sysv_set_status_do ($priority, $service, $active, 0);
+}
+
+sub gst_service_sysv_force_status
+{
+ my ($priority, $service, $active) = @_;
+
+ return &gst_service_sysv_set_status_do ($priority, $service, $active, 1);
+}
+
+sub gst_service_sysv_install_script
+{
+ my ($service, $file) = @_;
+ my ($res, $rcd_path, $initd_path);
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ if (!copy ("$FILESDIR/$file", "$initd_path/$service"))
+ {
+ &gst_report ("file_copy_failed", "$FILESDIR/$file", "$initd_path/$service");
+ return -1;
+ }
+
+ chmod (0755, "$initd_path/$service");
+
+ return 0;
+}
+
+# THESE ARE THE FUNCTIONS WHICH EXTRACT THE CONFIGURATION FROM THE COMPUTER
+
+# we are going to extract the name of the script
+sub gst_service_sysv_get_service_name
+{
+ my ($service) = @_;
+
+ $service =~ s/$initd_path\///;
+
+ return $service;
+}
+
+# This function gets the state of the service along the runlevels,
+# it also returns the average priority
+sub gst_service_sysv_get_runlevels_status
+{
+ my ($service) = @_;
+ my ($link);
+ my ($runlevel, $action, $priority);
+ my (@arr, @ret);
+
+ foreach $link (<$rcd_path/rc[0-6].d/[SK][0-9][0-9]$service>)
+ {
+ $link =~ s/$rcd_path\///;
+ $link =~ /rc([0-6])\.d\/([SK])([0-9][0-9]).*/;
+ ($runlevel,$action,$priority)=($1,$2,$3);
+ if ($action eq "S")
+ {
+ push @arr, { "name" => $runlevel,
+ "priority" => $priority,
+ "action" => "start" };
+ }
+ elsif ($action eq "K")
+ {
+ push @arr, { "name" => $runlevel,
+ "priority" => (100 - $priority),
+ "action" => "stop" };
+ }
+ }
+
+ return undef if (scalar(@arr) eq 0);
+
+ push @ret, { "runlevel" => \@arr };
+ return \@ret;
+}
+
+# We are going to extract the information of the service
+sub gst_service_sysv_get_service_info
+{
+ my ($service) = @_;
+ my ($script, @actions, @runlevels);
+ my %hash, $role;
+
+ # Return if it's a directory
+ return undef if (-d $service);
+
+ # We have to check if the service is executable
+ return undef unless (-x $service);
+
+ $script = &gst_service_sysv_get_service_name ($service);
+
+ # We have to check out if the service is in the "forbidden" list
+ return undef if (&gst_service_list_service_is_forbidden ($script));
+
+ $runlevels = &gst_service_sysv_get_runlevels_status($script);
+
+ $hash{"script"} = $script;
+ $hash{"runlevels"} = $runlevels unless ($runlevels eq undef);
+ $hash{"role"} = &gst_service_get_role ($script);
+
+ return \%hash;
+}
+
+# This function gets an ordered array of the available services from a SysV system
+sub gst_service_sysv_get_services
+{
+ my ($service);
+ my (@arr,%ret);
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ foreach $service (<$initd_path/*>)
+ {
+ my (%hash);
+ $hash = &gst_service_sysv_get_service_info ($service);
+ if ($hash ne undef)
+ {
+ $ret{$service} = $hash;
+ }
+ }
+
+ return \%ret;
+}
+
+# This functions get an ordered array of the available services from a file-rc system
+sub gst_service_filerc_get_runlevels_status
+{
+ my ($start_service, $stop_service, $priority) = @_;
+ my (@arr, @ret);
+
+ # we start with the runlevels in which the service starts
+ if ($start_service !~ /-/) {
+ my (@runlevels);
+
+ @runlevels = split /,/, $start_service;
+
+ foreach $runlevel (@runlevels)
+ {
+ push @arr, { "name" => $runlevel,
+ "action" => "start",
+ "priority" => $priority};
+ }
+ }
+
+ # now let's go with the runlevels in which the service stops
+ if ($stop_service !~ /-/) {
+ my (@runlevels);
+
+ @runlevels = split /,/, $stop_service;
+
+ foreach $runlevel (@runlevels)
+ {
+ push @arr, { "name" => $runlevel,
+ "action" => "stop",
+ "priority" => $priority};
+ }
+ }
+
+ push @ret, {"runlevel" => \@arr};
+ return \@ret;
+}
+
+sub gst_service_filerc_get_service_info
+{
+ my ($line, %ret) = @_;
+ my %hash;
+ my @runlevels;
+
+ if ($line =~ /^([0-9][0-9])[\t ]+([0-9\-S,]+)[\t ]+([0-9\-S,]+)[\t ]+\/etc\/init\.d\/(.*)/)
+ {
+ $priority = $1;
+ $stop_service = $2;
+ $start_service = $3;
+ $script = $4;
+
+ return undef if (&gst_service_list_service_is_forbidden ($script));
+
+ $hash{"script"} = $script;
+
+ $hash{"runlevels"} = &gst_service_filerc_get_runlevels_status ($start_service, $stop_service, $priority);
+ $hash{"role"} = &gst_service_get_role ($script);
+
+ return (\%hash);
+ }
+
+ return undef;
+}
+
+sub gst_service_filerc_get_services
+{
+ my ($script);
+ my (%ret);
+
+ open FILE, "$gst_prefix/etc/runlevel.conf" or return undef;
+ while ($line = <FILE>)
+ {
+ if ($line !~ /^#.*/)
+ {
+ my (%hash);
+ my ($start_service, $stop_service);
+ $hash = &gst_service_filerc_get_service_info ($line);
+
+ if ($hash ne undef)
+ {
+ $script = $$hash{"script"};
+
+ if ($ret{$script} eq undef)
+ {
+ $ret{$script} = $hash;
+ }
+ else
+ {
+ my (@runlevels);
+
+ # We need to mix the runlevels
+ @runlevels = $$hash{"runlevels"}[0]{"runlevel"};
+ foreach $runlevel (@runlevels)
+ {
+ push @{$ret{$script}{"runlevels"}[0]{"runlevel"}}, $runlevel;
+ }
+ }
+ }
+ }
+ }
+
+ return \%ret;
+}
+
+# this functions get a list of the services that run on a bsd init
+sub gst_service_bsd_get_service_info
+{
+ my ($service) = @_;
+ my ($script);
+ my (%hash);
+ my (@arr, @rl);
+
+ $script = $service;
+ $script =~ s/^.*\///;
+ $script =~ s/^rc\.//;
+
+ return undef if (! gst_file_exists ($service));
+
+ return undef if (&gst_service_list_service_is_forbidden ($script));
+
+ $hash {"script"} = $service;
+
+ # we hardcode the fourth runlevel, it's the graphical one
+ if ( -x $service)
+ {
+ push @arr, { "name" => 4,
+ "action" => "start" };
+ }
+ else
+ {
+ push @arr, { "name" => 4,
+ "action" => "stop" };
+ }
+
+ push @rl, { "runlevel" => \@arr };
+
+ $hash{"runlevels"} = \@rl;
+ $hash{"role"} = &gst_service_get_role ($script);
+
+ return \%hash;
+}
+
+sub gst_service_bsd_get_services
+{
+ my (%ret);
+ my ($files) = [ "rc.M", "rc.inet2", "rc.4" ];
+ my ($file);
+
+ foreach $i (@$files)
+ {
+ $file = "/etc/rc.d/" . $i;
+ $fd = &gst_file_open_read_from_names ($file);
+
+ if (!$fd) {
+ &gst_report ("rc_file_read_failed", $file);
+ return undef;
+ }
+
+ while (<$fd>)
+ {
+ $line = $_;
+
+ if ($line =~ /^if[ \t]+\[[ \t]+\-x[ \t]([0-9a-zA-Z\/\.\-_]+) .*\]/)
+ {
+ my (%hash);
+ $service = $1;
+
+ $hash = &gst_service_bsd_get_service_info ($service);
+
+ if ($hash ne undef)
+ {
+ $ret{$service} = $hash;
+ }
+ }
+ }
+
+ gst_file_close ($fd);
+ }
+
+ return \%ret;
+}
+
+# these functions get a list of the services that run on a gentoo init
+sub gst_service_gentoo_get_service_status
+{
+ my ($script, $runlevel) = @_;
+ my ($services) = &gst_service_gentoo_get_services_by_runlevel ($runlevel);
+
+ foreach $i (@$services)
+ {
+ return 1 if ($i eq $script);
+ }
+
+ return 0;
+}
+
+sub gst_service_gentoo_get_runlevels
+{
+ my($raw_output) = gst_file_run_backtick("rc-status -l");
+ my(@runlevels) = split(/\n/,$raw_output);
+
+ return @runlevels;
+}
+
+sub gst_service_gentoo_get_services_by_runlevel
+{
+ my($runlevel) = @_;
+ my($raw_output) = gst_file_run_backtick("rc-status $runlevel");
+ my(@raw_lines) = split(/\n/,$raw_output);
+ my(@services);
+ my($line);
+
+ foreach $line (@raw_lines)
+ {
+ if ($line !~ /^Runlevel/)
+ {
+ $line=(split(" ",$line))[0];
+ push(@services,$line);
+ }
+ }
+
+ return \@services
+}
+
+sub gst_service_gentoo_get_services_list
+{
+ return &gst_service_sysv_list_dir ("/etc/init.d/");
+}
+
+sub gst_service_gentoo_service_exist
+{
+ my($service) = @_;
+ my($services) = &gst_service_gentoo_get_services_list();
+
+ foreach $i (@$services)
+ {
+ return 1 if ($i =~ /$service/);
+ }
+
+ return 0;
+}
+
+sub gst_service_gentoo_get_runlevels_by_service
+{
+ my ($service) = @_;
+ my(@runlevels,@services_in_runlevel,@contain_runlevels, $runlevel);
+ my ($elem);
+
+ # let's do some caching to improve performance
+ if ($gentoo_services_hash eq undef)
+ {
+ @runlevels = &gst_service_gentoo_get_runlevels ();
+
+ foreach $runlevel (@runlevels)
+ {
+ $$gentoo_services_hash{$runlevel} = &gst_service_gentoo_get_services_by_runlevel ($runlevel);
+ }
+ }
+
+ if (&gst_service_gentoo_service_exist($service))
+ {
+ foreach $runlevel (keys %$gentoo_services_hash)
+ {
+ $services_in_runlevel = $$gentoo_services_hash {$runlevel};
+
+ foreach $elem (@$services_in_runlevel)
+ {
+ push (@contain_runlevels, $runlevel) if ($elem eq $service);
+ }
+ }
+ }
+
+ return @contain_runlevels;
+}
+
+sub gst_service_gentoo_runlevel_status_by_service
+{
+ my ($service) = @_;
+ my (@arr, @ret);
+ my (@runlevels) = &gst_service_gentoo_get_runlevels();
+ my (@started) = &gst_service_gentoo_get_runlevels_by_service($service);
+ my (%start_runlevels) = map { $started[$_], 1 } 0 .. $#started;
+
+ foreach $runlevel (@runlevels)
+ {
+ if (defined $start_runlevels{$runlevel})
+ {
+ push @arr, { "name" => $runlevel,
+ "action" => "start" };
+ }
+ else
+ {
+ push @arr, { "name" => $runlevel,
+ "action" => "stop" };
+ }
+ }
+
+ push @ret, { "runlevel" => \@arr };
+ return @ret;
+}
+
+sub gst_service_gentoo_get_service_info
+{
+ my ($service) = @_;
+ my ($script, @actions, @runlevels);
+ my %hash;
+
+ # We have to check out if the service is in the "forbidden" list
+ return undef if (&gst_service_list_service_is_forbidden ($service));
+
+ my($runlevels) = &gst_service_gentoo_runlevel_status_by_service ($service);
+
+ $hash{"script"} = $service;
+ $hash{"runlevels"} = $runlevels unless ($runlevels eq undef);
+ $hash{"role"} = &gst_service_get_role ($service);
+
+ return \%hash;
+}
+
+sub gst_service_gentoo_get_services
+{
+ my ($service);
+ my (%ret);
+ my ($service_list) = &gst_service_gentoo_get_services_list ();
+
+ foreach $service (@$service_list)
+ {
+ my (%hash);
+ $hash = &gst_service_gentoo_get_service_info ($service);
+
+ $ret{$service} = $hash if ($hash ne undef);
+ }
+
+ return \%ret;
+}
+
+# rcNG functions, mostly for FreeBSD
+
+
+sub gst_service_archlinux_status_by_service
+{
+ my ($service) = @_;
+ return 1 if( -f "/var/run/daemons/$service");
+ return 0;
+}
+
+sub gst_service_rcng_status_by_service
+{
+ my ($service) = @_;
+ my ($fd, $line, $active);
+
+ $fd = &gst_file_run_pipe_read ("/etc/rc.d/$service rcvar");
+
+ while (<$fd>)
+ {
+ $line = $_;
+
+ if ($line =~ /^\$.*=YES$/)
+ {
+ $active = 1;
+ last;
+ }
+ }
+
+ gst_file_close ($fd);
+ return $active;
+}
+
+sub gst_service_rcng_get_service_info
+{
+ my ($service) = @_;
+ my ($script, @actions, @runlevels);
+ my (%hash, @arr, @rl);
+
+ # We have to check if the service is in the "forbidden" list
+ return undef if (&gst_service_list_service_is_forbidden ($service));
+
+ $hash{"script"} = $service;
+
+ if (gst_service_rcng_status_by_service ($service))
+ {
+ push @arr, { "name" => "rc",
+ "action" => "start" };
+ }
+ else
+ {
+ push @arr, { "name" => "rc",
+ "action" => "stop" };
+ }
+
+ push @rl, { "runlevel", \@arr };
+
+ $hash {"runlevels"} = \@rl;
+ $hash{"role"} = &gst_service_get_role ($service);
+
+ return \%hash;
+}
+
+sub gst_service_archlinux_get_service_info
+{
+ my ($service) = @_;
+ my ($script, @actions, @runlevels);
+ my (%hash, @arr, @rl);
+
+ # We have to check if the service is in the "forbidden" list
+ return undef if (&gst_service_list_service_is_forbidden ($service));
+
+ $hash{"script"} = $service;
+
+ if (&gst_service_archlinux_status_by_service ($service))
+ {
+ push @arr, { "name" => "rc",
+ "action" => "start" };
+ }
+ else
+ {
+ push @arr, { "name" => "rc",
+ "action" => "stop" };
+ }
+
+ push @rl, { "runlevel", \@arr };
+
+ $hash {"runlevels"} = \@rl;
+ $hash{"role"} = &gst_service_get_role ($service);
+
+ return \%hash;
+}
+
+sub gst_service_archlinux_get_services
+{
+ my ($service);
+ my (%ret);
+
+ foreach $service (<$gst_prefix/etc/rc.d/*>)
+ {
+ my (%hash);
+
+ $service =~ s/.*\///;
+ $hash = &gst_service_archlinux_get_service_info ($service);
+
+ $ret{$service} = $hash if ($hash ne undef);
+ }
+
+ return \%ret;
+}
+
+sub gst_service_rcng_get_services
+{
+ my ($service);
+ my (%ret);
+
+ foreach $service (<$gst_prefix/etc/rc.d/*>)
+ {
+ my (%hash);
+
+ $service =~ s/.*\///;
+ $hash = &gst_service_rcng_get_service_info ($service);
+
+ $ret{$service} = $hash if ($hash ne undef);
+ }
+
+ return \%ret;
+}
+# SuSE functions, quite similar to SysV, but not equal...
+sub gst_service_suse_get_service_info ($service)
+{
+ my ($service) = @_;
+ my (%hash, @arr, @ret);
+
+ # We have to check if the service is in the "forbidden" list
+ return undef if (&gst_service_list_service_is_forbidden ($service));
+
+ $hash{"script"} = $service;
+
+ foreach $link (<$rcd_path/rc[0-9S].d/S[0-9][0-9]$service>)
+ {
+ $link =~ s/$rcd_path\///;
+ $link =~ /rc([0-6])\.d\/S[0-9][0-9].*/;
+ $runlevel = $1;
+
+ push @arr, { "name" => $runlevel,
+ "action" => "start" };
+ }
+
+ foreach $link (<$rcd_path/boot.d/S[0-9][0-9]$service>)
+ {
+ push @arr, {"name" => "B",
+ "action" => "start" };
+ }
+
+ if (scalar @arr > 0)
+ {
+ push @ret, { "runlevel" => \@arr };
+ $hash{"runlevels"} = \@ret;
+ $hash{"role"} = &gst_service_get_role ($service);
+ }
+
+ return \%hash;
+}
+
+sub gst_service_suse_get_services
+{
+ my ($service, %ret);
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ foreach $service (<$gst_prefix/etc/init.d/*>)
+ {
+ my (%hash);
+
+ next if (-d $service || ! -x $service);
+
+ $service =~ s/.*\///;
+ $hash = &gst_service_suse_get_service_info ($service);
+
+ $ret{$service} = $hash if ($hash ne undef);
+ }
+
+ return \%ret;
+}
+
+# generic functions to get the available services
+sub gst_get_init_type
+{
+ if (($gst_dist =~ /debian/) && (stat ("$gst_prefix/etc/runlevel.conf")))
+ {
+ return "file-rc";
+ }
+ elsif ($gst_dist =~ /slackware/)
+ {
+ return "bsd";
+ }
+ elsif ($gst_dist =~ /freebsd/)
+ {
+ return "rcng";
+ }
+ elsif ($gst_dist =~ /archlinux/)
+ {
+ return "archlinux";
+ }
+ elsif (($gst_dist =~ /gentoo/) || ($gst_dist =~ /^vlos/))
+ {
+ return "gentoo";
+ }
+ elsif ($gst_dist =~ /suse/)
+ {
+ return "suse";
+ }
+ else
+ {
+ return "sysv";
+ }
+}
+
+sub gst_service_get_services
+{
+ $type = &gst_get_init_type ();
+
+ return &gst_service_sysv_get_services () if ($type eq "sysv");
+ return &gst_service_filerc_get_services () if ($type eq "file-rc");
+ return &gst_service_bsd_get_services () if ($type eq "bsd");
+ return &gst_service_gentoo_get_services () if ($type eq "gentoo");
+ return &gst_service_rcng_get_services () if ($type eq "rcng");
+ return &gst_service_suse_get_services () if ($type eq "suse");
+ return &gst_service_archlinux_get_services() if ($type eq "archlinux");
+ return undef;
+}
+
+
+# This function gets the runlevel that is in use
+sub gst_service_sysv_get_default_runlevel
+{
+ my (@arr);
+
+ @arr = split / /, `/sbin/runlevel` ;
+ $arr[1] =~ s/\n//;
+
+ return $arr[1];
+}
+
+sub gst_service_get_default_runlevel
+{
+ my ($type) = &gst_get_init_type ();
+
+ return "default" if ($type eq "gentoo");
+ return "rc" if ($type eq "rcng");
+ return "rc" if ($type eq "archlinux");
+ return &gst_service_sysv_get_default_runlevel ();
+}
+
+
+# THESE ARE THE FUNCTIONS WHICH APPLY THE CHANGES MADE TO THE CONFIGURATION OF THE COMPUTER
+
+sub gst_service_sysv_add_link
+{
+ my ($runlevel, $action, $priority, $service) = @_;
+ my ($prio) = sprintf ("%0.2d",$priority);
+
+ symlink ("$relative_path/$service", "$rcd_path/rc$runlevel.d/$action$prio$service");
+
+ &gst_report_enter ();
+ &gst_report ("service_sysv_add_link", "$rcd_path/rc$runlevel.d/$action$prio$service");
+ &gst_report_leave ();
+}
+
+sub gst_service_sysv_remove_link
+{
+ my ($runlevel, $script) = @_;
+
+ foreach $link (<$rcd_path/rc$runlevel.d/[SK][0-9][0-9]$script>)
+ {
+ &gst_report ("service_sysv_remove_link", "$link");
+ unlink ("$link");
+ &gst_report_leave ();
+ }
+}
+
+
+# These are the functions for storing the service settings from XML in SysV
+sub gst_service_sysv_set_service
+{
+ my ($service) = @_;
+ my ($script, $priority, $runlevels);
+ my ($action);
+
+ ($rcd_path, $initd_path, $relative_path) = &gst_service_sysv_get_paths ();
+
+ $script = $$service{"script"};
+ $runlevels = $$service{"runlevels"}[0]{"runlevel"};
+
+ # pass though all the runlevels checking if the service must be started, stopped or removed
+ for ($i = 0; $i <= 6; $i++)
+ {
+ &gst_service_sysv_remove_link ($i, $script);
+
+ $action = undef;
+ foreach $j (@$runlevels)
+ {
+ if ($i == $$j{"name"})
+ {
+ $found = 1;
+ $action = $$j{"action"};
+ $priority = $$j{"priority"};
+ $priority = 50 if (!$priority); #very rough guess
+ }
+ }
+
+ if ($action ne undef)
+ {
+ if ($action eq "start")
+ {
+ &gst_service_sysv_add_link ($i, "S", $priority, $script);
+ }
+ else
+ {
+ &gst_service_sysv_add_link ($i, "K", 100 - $priority, $script);
+ }
+ }
+ }
+}
+
+sub gst_service_sysv_set_services
+{
+ my ($services, $runlevel) = @_;
+
+ foreach $i (@$services)
+ {
+ &gst_service_sysv_set_service($i);
+ }
+}
+
+sub gst_service_filerc_concat_runlevels
+{
+ my (@runlevels) = @_;
+
+ $str = join (",", sort (@runlevels));
+ return ($str) ? $str : "-";
+}
+
+sub gst_service_filerc_set_service
+{
+ my ($buff, $service) = @_;
+ my (%hash, $priority, $line, $str);
+
+ $arr = $$service{"runlevels"}[0]{"runlevel"};
+
+ foreach $i (@$arr)
+ {
+ $priority = 0 + $$i{"priority"};
+ $priority = 50 if ($priority == 0); #very rough guess
+
+ if ($$i{"action"} eq "start")
+ {
+ $hash{$priority}{"start"} = [] if (!$hash{$priority}{"start"});
+ push @{$hash{$priority}{"start"}}, $$i{"name"};
+ }
+ else
+ {
+ $hash{$priority}{"stop"} = [] if (!$hash{$priority}{"stop"});
+ push @{$hash{$priority}{"stop"}}, $$i{"name"};
+ }
+ }
+
+ foreach $priority (keys %hash)
+ {
+ $line = sprintf ("%0.2d", $priority) . "\t";
+ $line .= &gst_service_filerc_concat_runlevels (@{$hash{$priority}{"stop"}}) . "\t";
+ $line .= &gst_service_filerc_concat_runlevels (@{$hash{$priority}{"start"}}) . "\t";
+ $line .= "/etc/init.d/" . $$service{"script"} . "\n";
+
+ push @$buff, $line;
+ }
+}
+
+# This is the function for storing the service settings from XML in file-rc
+sub gst_service_filerc_set_services
+{
+ my ($services, $runlevel) = @_;
+ my ($buff, $lineno, $line, $file);
+ my ($rcd_path, $initd_path, $relative_path) = &gst_service_sysv_get_paths ();
+
+ $file = "$gst_prefix/etc/runlevel.conf";
+
+ $buff = &gst_file_buffer_load ($file);
+ &gst_file_buffer_join_lines ($buff);
+
+ $lineno = 0;
+
+ # We prepare the file for storing the configuration, save the initial comments
+ # and delete the rest
+ while ($$buff[$lineno] =~ /^#.*/)
+ {
+ $lineno++;
+ }
+
+ for ($i = $lineno; $i < scalar (@$buff); $i++)
+ {
+ $$buff[$i] =~ /.*\/etc\/init\.d\/(.*)/;
+
+ # we need to keep the forbidden services and the services that only start in rcS.d
+ if (!gst_service_list_service_is_forbidden ($1))
+ {
+ delete $$buff[$i];
+ }
+ }
+
+ # Now we append the services
+ foreach $service (@$services)
+ {
+ &gst_service_filerc_set_service ($buff, $service);
+ }
+
+ @$buff = sort @$buff;
+
+ push @$buff, "\n";
+ &gst_file_buffer_clean ($buff);
+ &gst_file_buffer_save ($buff, $file);
+}
+
+sub gst_service_bsd_set_services
+{
+ my ($services, $runlevel) = @_;
+ my ($script, $runlevels);
+
+ foreach $service (@$services)
+ {
+ $script = $$service{"script"};
+ $runlevels = $$service{"runlevels"}[0]{"runlevel"}[0];
+
+ $action = $$runlevels {"action"};
+
+ if ($action eq "start")
+ {
+ &gst_file_run ("chmod ugo+x $script");
+ }
+ else
+ {
+ &gst_file_run ("chmod ugo-x $script");
+ }
+ }
+}
+
+sub gst_service_gentoo_set_services
+{
+ my ($services, $runlevel) = @_;
+ my ($action);
+
+ foreach $service (@$services)
+ {
+ $script = $$service{"script"};
+ $arr = $$service{"runlevels"}[0]{"runlevel"};
+
+ foreach $i (@$arr)
+ {
+ $action = $$i{"action"};
+ $rl = $$i{"name"};
+
+ if ( $action eq "start")
+ {
+ &gst_file_run ("rc-update add $script $rl");
+ }
+ elsif ($action eq "stop")
+ {
+ &gst_file_run ("rc-update del $script $rl");
+ }
+ }
+ }
+}
+
+sub gst_service_rcng_set_status
+{
+ my ($service, $action) = @_;
+ my ($fd, $key, $res);
+ my ($default_rcconf) = "/etc/defaults/rc.conf";
+ my ($rcconf) = "/etc/rc.conf";
+
+ if (&gst_file_exists ("/etc/rc.d/$service"))
+ {
+ $fd = &gst_file_run_pipe_read ("/etc/rc.d/$service rcvar");
+
+ while (<$fd>)
+ {
+ if (/^\$(.*)=.*$/)
+ {
+ # to avoid cluttering rc.conf with duplicated data,
+ # we first look in the defaults/rc.conf for the key
+ $key = $1;
+ $res = &gst_parse_sh_bool ($default_rcconf, $key);
+
+ if ($res == $action)
+ {
+ &gst_replace_sh ($rcconf, $key);
+ }
+ else
+ {
+ &gst_replace_sh_bool ($rcconf, $key, "YES", "NO", $action);
+ }
+ }
+ }
+
+ &gst_file_close ($fd);
+ }
+ elsif (&gst_file_exists ("/usr/local/etc/rc.d/$service.sh"))
+ {
+ if ($action)
+ {
+ gst_file_copy ("/usr/local/etc/rc.d/$service.sh.sample",
+ "/usr/local/etc/rc.d/$service.sh");
+ }
+ else
+ {
+ gst_file_remove ("/usr/local/etc/rc.d/$service.sh");
+ }
+ }
+}
+
+sub gst_service_rcng_set_services
+{
+ my ($services, $runlevel) = @_;
+ my ($action, $runlevels, $script);
+
+ foreach $service (@$services)
+ {
+ $script = $$service {"script"};
+ $runlevels = $$service{"runlevels"}[0]{"runlevel"}[0];
+ $action = ($$runlevels {"action"} eq "start")? 1 : 0;
+
+ &gst_service_rcng_set_status ($script, $action);
+ }
+}
+
+sub gst_service_suse_set_services
+{
+ my ($services, $runlevel) = @_;
+ my ($action, $runlevels, $script, $rllist);
+
+ foreach $service (@$services)
+ {
+ $script = $$service{"script"};
+ $runlevels = $$service{"runlevels"}[0]{"runlevel"};
+ $rllist = "";
+
+ &gst_file_run ("insserv -r $script");
+
+ foreach $rl (@$runlevels)
+ {
+ if ($$rl{"action"} eq "start")
+ {
+ $rllist .= $$rl{"name"} . ",";
+ }
+ }
+
+ if ($rllist ne "")
+ {
+ $rllist =~ s/,$//;
+
+ &gst_file_run ("insserv $script,start=$rllist");
+ }
+ }
+}
+
+
+sub gst_service_archlinux_set_status
+{
+ my ($script, $active) = @_;
+ my $rcconf = '/etc/rc.conf';
+ open DATA, "$rcconf";
+ my @rcconflines = <DATA>;
+ close (DATA);
+ open DATAOUT, ">", "$rcconf";
+ if(($active) && (! -f "/var/run/daemons/$script"))
+ {
+ &gst_service_archlinux_run_script($script,"start");
+ }
+ if((!$active) && ( -f "/var/run/daemons/$script"))
+ {
+ &gst_service_archlinux_run_script($script,"start");
+ }
+
+
+ foreach my $line (@rcconflines)
+ {
+ if($line =~ /\DAEMONS=/)
+ {
+ if($line =~ m/$script/)
+ {
+ if(!$active)
+ {
+ $line =~ s/$script //;
+ }
+ }
+ else
+ {
+ if($active)
+ {
+ $line =~ s/network/network $script/g;
+ }
+ }
+ }
+ print DATAOUT "$line";
+ }
+
+ close (DATAOUT);
+}
+
+sub gst_service_archlinux_set_services
+{
+ my ($services, $runlevel) = @_;
+ my ($action, $runlevels, $script);
+ foreach $service (@$services)
+ {
+ $script = $$service {"script"};
+ $runlevels = $$service{"runlevels"}[0]{"runlevel"}[0];
+ $action = ($$runlevels {"action"} eq "start")? 1 : 0;
+ &gst_service_archlinux_set_status ($script, $action);
+ }
+}
+
+sub gst_service_set_services
+{
+ my ($services, $runlevel) = @_;
+
+ $type = &gst_get_init_type ();
+ &gst_service_sysv_set_services ($services, $runlevel) if ($type eq "sysv");
+ &gst_service_filerc_set_services ($services, $runlevel) if ($type eq "file-rc");
+ &gst_service_bsd_set_services ($services, $runlevel) if ($type eq "bsd");
+ &gst_service_gentoo_set_services ($services, $runlevel) if ($type eq "gentoo");
+ &gst_service_rcng_set_services ($services, $runlevel) if ($type eq "rcng");
+ &gst_service_suse_set_services ($services, $runlevel) if ($type eq "suse");
+ &gst_service_archlinux_set_services ($services, $runlevel) if ($type eq "archlinux");
+}
+
+sub gst_service_set_conf
+{
+ my ($hash) = @_;
+ my ($services, $runlevel);
+
+ return unless $hash;
+ $services = $$hash{"services"}[0]{"service"};
+ return unless $services;
+ $runlevel = $$hash{"runlevel"};
+ return unless $runlevel;
+
+ &gst_service_set_services($services, $runlevel);
+}
+
+# stuff for checking whether service is running
+sub gst_service_debian_get_status
+{
+ my ($service) = @_;
+ my ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+ my ($output, $pidfile);
+
+ $output = `grep "\/var\/run\/.*\.pid" $initd_path\/$service`;
+
+ if ($output =~ /.*(\/var\/run\/.*\.pid).*/ )
+ {
+ $pidfile = $1;
+ $pidval = `cat $pidfile`;
+
+ return 0 if $pidval eq "";
+
+ $pid = `ps h $pidval`;
+
+ if ($pid eq "")
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ return undef;
+}
+
+sub gst_service_redhat_get_status
+{
+ my ($service) = @_;
+ my ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ if (-f "/var/lock/subsys/$service")
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+sub gst_service_gentoo_get_status
+{
+ my ($service) = @_;
+
+ $line = `/etc/init.d/$service status`;
+
+ return 1 if ($line =~ /started/);
+ return 0;
+}
+
+sub gst_service_rcng_get_status
+{
+ my ($service) = @_;
+
+ $line = gst_file_run_backtick ("/etc/rc.d/$service forcestatus");
+ return 1 if ($line =~ /pid [0-9]*/);
+
+ # hacky as hell, we need to check services in /usr/local/etc/rc.d
+ # and there's no standard way to check they're running
+ return 1 if (-f "/var/run/$service.pid");
+
+ # we give up, the service isn't running
+ return 0;
+}
+sub gst_service_archlinux_get_status
+{
+ my ($service) = @_;
+ return 1 if( -f "/var/run/daemons/$service");
+ return 0;
+}
+
+sub gst_service_suse_get_status
+{
+ my ($service) = @_;
+
+ $line = gst_file_run_backtick ("/etc/init.d/$service status");
+ return 1 if ($line =~ /running/);
+ return 0;
+}
+
+# returns true if the service is already running
+sub gst_service_get_status
+{
+ my ($service) = @_;
+ my %dist_map =
+ (
+ "debian-2.2" => \&gst_service_debian_get_status,
+ "debian-3.0" => \&gst_service_debian_get_status,
+ "debian-3.1" => \&gst_service_debian_get_status,
+ "debian-4.0" => \&gst_service_debian_get_status,
+ "debian-5.0" => \&gst_service_debian_get_status,
+ "debian-testing" => \&gst_service_debian_get_status,
+ "ubuntu-5.04" => \&gst_service_debian_get_status,
+ "ubuntu-5.10" => \&gst_service_debian_get_status,
+ "ubuntu-6.06" => \&gst_service_debian_get_status,
+ "ubuntu-6.10" => \&gst_service_debian_get_status,
+ "ubuntu-7.04" => \&gst_service_debian_get_status,
+ "ubuntu-7.10" => \&gst_service_debian_get_status,
+ "ubuntu-8.04" => \&gst_service_debian_get_status,
+
+ "redhat-5.2" => \&gst_service_redhat_get_status,
+ "redhat-6.0" => \&gst_service_redhat_get_status,
+ "redhat-6.1" => \&gst_service_redhat_get_status,
+ "redhat-6.2" => \&gst_service_redhat_get_status,
+ "redhat-7.0" => \&gst_service_redhat_get_status,
+ "redhat-7.1" => \&gst_service_redhat_get_status,
+ "redhat-7.2" => \&gst_service_redhat_get_status,
+ "redhat-7.3" => \&gst_service_redhat_get_status,
+ "redhat-8.0" => \&gst_service_redhat_get_status,
+ "redhat-9" => \&gst_service_redhat_get_status,
+ "mandrake-7.2" => \&gst_service_redhat_get_status,
+ "fedora-1" => \&gst_service_redhat_get_status,
+ "fedora-2" => \&gst_service_redhat_get_status,
+ "fedora-3" => \&gst_service_redhat_get_status,
+ "fedora-4" => \&gst_service_redhat_get_status,
+ "fedora-5" => \&gst_service_redhat_get_status,
+
+ "rpath" => \&gst_service_redhat_get_status,
+
+ "suse-9.0" => \&gst_service_suse_get_status,
+ "suse-9.1" => \&gst_service_suse_get_status,
+ "archlinux" => \&gst_service_archlinux_get_status,
+ "gentoo" => \&gst_service_gentoo_get_status,
+ "vlos-1.2" => \&gst_service_gentoo_get_status,
+
+ "freebsd-5" => \&gst_service_rcng_get_status,
+ "freebsd-6" => \&gst_service_rcng_get_status,
+ );
+ my $proc;
+
+ $proc = $dist_map {$gst_dist};
+
+ return undef if ($proc eq undef);
+
+ return &$proc ($service);
+}
+
+# Functions to run a service
+sub gst_service_sysv_run_initd_script
+{
+ my ($service, $arg) = @_;
+ my ($rc_path, $initd_path);
+ my $str;
+ my %map =
+ ("restart" => "restarted",
+ "stop" => "stopped",
+ "start" => "started");
+
+ &gst_report_enter ();
+
+ if (!exists $map{$arg})
+ {
+ &gst_report ("service_sysv_op_unk", $arg);
+ &gst_report_leave ();
+ return -1;
+ }
+
+ $str = $map{$arg};
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ if (-f "$initd_path/$service")
+ {
+ if (!&gst_file_run ("$initd_path/$service $arg"))
+ {
+ &gst_report ("service_sysv_op_success", $service, $str);
+ &gst_report_leave ();
+ return 0;
+ }
+ }
+
+ &gst_report ("service_sysv_op_failed", $service, $str);
+ &gst_report_leave ();
+ return -1;
+}
+
+sub gst_service_bsd_run_script
+{
+ my ($service, $arg) = @_;
+ my ($chmod) = 0;
+
+ return if (!&gst_file_exists ($service));
+
+ # if it's not executable then chmod it
+ if (!((stat ($service))[2] & (S_IXUSR || S_IXGRP || S_IXOTH)))
+ {
+ $chmod = 1;
+ &gst_file_run ("chmod ugo+x $service");
+ }
+
+ &gst_file_run ("$service $arg");
+
+ # return it to it's normal state
+ if ($chmod)
+ {
+ &gst_file_run ("chmod ugo-x $service");
+ }
+}
+
+sub gst_service_gentoo_run_script
+{
+ my ($service, $arg) = @_;
+ my ($option);
+
+ my %map =
+ ("stop" => "stopped",
+ "start" => "started"
+ );
+
+ &gst_report_enter ();
+
+ if (!exists $map{$arg})
+ {
+ &gst_report ("service_sysv_op_unk", $arg);
+ &gst_report_leave ();
+ return -1;
+ }
+
+ if (&gst_service_gentoo_service_exist ($service))
+ {
+ if (!&gst_file_run ("/etc/init.d/$service $arg"))
+ {
+ &gst_report ("service_sysv_op_success", $service, $str);
+ &gst_report_leave ();
+ return 0;
+ }
+ }
+
+ &gst_report ("service_sysv_op_failed", $service, $str);
+ &gst_report_leave ();
+ return -1;
+}
+
+
+sub gst_service_rcng_run_script
+{
+ my ($service, $arg) = @_;
+ my ($farg);
+
+ my %map =
+ ("stop" => "forcestop",
+ "start" => "forcestart"
+ );
+
+ &gst_report_enter ();
+
+ if (!exists $map{$arg})
+ {
+ &gst_report ("service_sysv_op_unk", $arg);
+ &gst_report_leave ();
+ return -1;
+ }
+
+ $farg = $map {$arg};
+
+ if (!&gst_file_run ("/etc/rc.d/$service $farg"))
+ {
+ &gst_report ("service_sysv_op_success", $service, $str);
+ &gst_report_leave ();
+ return 0;
+ }
+
+ &gst_report ("service_sysv_op_failed", $service, $str);
+ &gst_report_leave ();
+ return -1;
+}
+
+sub gst_service_archlinux_run_script
+{
+ my ($service, $arg) = @_;
+ my ($farg);
+
+ my %map =
+ ("stop" => "stop",
+ "start" => "start"
+ );
+
+ &gst_report_enter ();
+
+ if (!exists $map{$arg})
+ {
+ &gst_report ("service_sysv_op_unk", $arg);
+ &gst_report_leave ();
+ return -1;
+ }
+
+ $farg = $map {$arg};
+
+ if (!&gst_file_run ("/etc/rc.d/$service $farg"))
+ {
+ &gst_report ("service_sysv_op_success", $service, $str);
+ &gst_report_leave ();
+ return 0;
+ }
+
+ &gst_report ("service_sysv_op_failed", $service, $str);
+ &gst_report_leave ();
+ return -1;
+}
+sub gst_service_run_script
+{
+ my ($service, $arg) = @_;
+ my ($proc, $type);
+ my %map =
+ (
+ "file-rc" => \&gst_service_sysv_run_initd_script,
+ "sysv" => \&gst_service_sysv_run_initd_script,
+ "bsd" => \&gst_service_bsd_run_script,
+ "gentoo" => \&gst_service_gentoo_run_script,
+ "rcng" => \&gst_service_rcng_run_script,
+ "suse" => \&gst_service_sysv_run_initd_script,
+ "archlinux" => \&gst_service_archlinux_run_script,
+ );
+
+ $type = &gst_get_init_type ();
+
+ $proc = $map {$type};
+
+ &$proc ($service, $arg);
+}
+
+# functions to know if a service will be installed
+sub gst_service_sysv_installed
+{
+ my ($service) = @_;
+ my ($res, $rcd_path, $initd_path);
+
+ &gst_report_enter ();
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+
+ $res = 1;
+ if (! -f "$initd_path/$service")
+ {
+ $res = 0;
+ &gst_report ("service_sysv_not_found", $service);
+ }
+
+ &gst_report_leave ();
+ return $res;
+}
+
+sub gst_service_bsd_installed
+{
+ my ($service) = @_;
+
+ return 1 if ( -f "$service");
+ return 0;
+}
+
+sub gst_service_gentoo_installed
+{
+ my ($service) = @_;
+
+ return 1 if ( -f "/etc/init.d/$service");
+ return 0;
+}
+
+sub gst_service_rcng_installed
+{
+ my ($service) = @_;
+
+ return 1 if ( -f "/etc/rc.d/$service");
+ return 1 if ( -f "/usr/local/etc/rc.d/$service.sh.sample");
+ return 0;
+}
+
+sub gst_service_installed
+{
+ my ($service) = @_;
+ my ($type);
+ $type = &gst_get_init_type ();
+
+ return &gst_service_sysv_installed ($service) if (($type eq "sysv") || ($type eq "file-rc") || ($type eq "suse"));
+ return &gst_service_bsd_installed ($service) if ($type eq "bsd");
+ return &gst_service_gentoo_installed ($service) if ($type eq "gentoo");
+ return &gst_service_rcng_installed ($service) if ($type eq "rcng");
+ return &gst_service_rcng_installed ($service) if ($type eq "archlinux");
+ return 0;
+}
+
+sub gst_service_list_any_installed
+{
+ my @service = @_;
+ my $res;
+
+ $res = 0;
+
+ foreach $serv (@service)
+ {
+ if (gst_service_installed ($serv))
+ {
+ $res = 1;
+ }
+ }
+
+ return $res;
+}
+
+sub gst_service_bsd_set_status
+{
+ my ($script, $active) = @_;
+ my (@arr);
+
+ if ($active)
+ {
+ &gst_file_run ("chmod ugo+x $script");
+ &gst_service_run_script ($script, "start");
+ }
+ else
+ {
+ &gst_service_run_script ($script, "stop");
+ &gst_file_run ("chmod ugo-x $script");
+ }
+}
+
+sub gst_service_gentoo_set_status
+{
+ my ($script, $force_now, $active) = @_;
+ my (@arr);
+
+ if ($active)
+ {
+ &gst_file_run ("rc-update add $script default");
+ &gst_file_run ("/etc/init.d/$script start") if ($force_now == 1);
+ }
+ else
+ {
+ &gst_file_run ("rc-update del $script default");
+ &gst_file_run ("/etc/init.d/$script stop") if ($force_now == 1);
+ }
+}
+
+sub gst_service_suse_set_status
+{
+ my ($script, $active) = @_;
+ my (@runlevels, $rllist);
+ my ($rcd_path, $initd_path);
+ my ($rl);
+
+ ($rcd_path, $initd_path) = &gst_service_sysv_get_paths ();
+ @runlevels = &gst_service_sysv_get_runlevels ();
+
+ if ($active)
+ {
+ $rllist = join ",", @runlevels;
+ &gst_file_run ("insserv $script,start=$rllist");
+ &gst_service_run_script ($script, "start");
+ }
+ else
+ {
+ # to remove a service from a few runlevels we need to run
+ # insserv -r and then insserv blah,start=x,y,z
+ foreach $link (<$rcd_path/rc[0-9S].d/S[0-9][0-9]$script>)
+ {
+ $link =~ s/$rcd_path\///;
+ $link =~ /rc([0-9S])\.d\/S[0-9][0-9].*/;
+ $rllist .= "$1,";
+ }
+
+ foreach $link (<$rcd_path/boot.d/S[0-9][0-9]$service>)
+ {
+ $rllist .= "B,";
+ }
+
+ # remove the default runlevels from the list
+ foreach $runlevel (@runlevels)
+ {
+ $rllist =~ s/$runlevel,//;
+ }
+
+ $rllist =~ s/,$//;
+
+ &gst_file_run ("insserv -r $script");
+
+ if ($rllist ne "")
+ {
+ &gst_file_run ("insserv $script,start=$rllist");
+ }
+
+ &gst_service_run_script ($script, "stop");
+ }
+}
diff --git a/knetworkconf/backends/system-tools-backends.pc.in b/knetworkconf/backends/system-tools-backends.pc.in
new file mode 100644
index 0000000..185778f
--- /dev/null
+++ b/knetworkconf/backends/system-tools-backends.pc.in
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=
+libdir=
+includedir=
+
+filessdir=@filesdir@
+backenddir=@scriptsdir@
+
+Name: gst-backends
+Description: GNOME System Tools backends
+Version: @VERSION@
+Requires:
+Libs:
+Cflags:
diff --git a/knetworkconf/backends/type1inst b/knetworkconf/backends/type1inst
new file mode 100755
index 0000000..86d6425
--- /dev/null
+++ b/knetworkconf/backends/type1inst
@@ -0,0 +1,1387 @@
+#!/usr/bin/perl
+#
+# You may need to change the above path.
+#
+#-----------------------------------------------------------------------------
+#
+# Copyright (C) 1996-1998 James Macnicol
+#
+# 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, 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 MERCHANTIBILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+#-----------------------------------------------------------------------------
+#
+# type1inst : Generate a "fonts.scale" file for Type 1 fonts in PFB format
+# for use with your favourite X server. Also generate a "Fontmap" for use
+# with ghostscript.
+#
+# cd to the directory you want to install fonts in and invoke this script.
+# Options:
+#
+# -samples Create sample PS files for each font
+# -nox Do not create fonts.scale and fonts.dir for X11
+# -nogs Do not create Fontmap for GhostScript
+# -quiet Don't print anything on the stdout, just to the log
+# (see also next section).
+# -silent Same as -quiet (for backwards compatiblity)
+# -q Same as -quiet
+# -nolog Don't create a log file
+# -version Print version info and quit
+# -v Same as -version
+#
+#
+#
+# THIS IS BETA SOFTWARE! PLEASE READ THE "README" FILE!!!
+#
+# Direct all correspondence regarding this software to
+#
+# J.Macnicol@student.anu.edu.au
+#
+#
+# Good luck!
+#
+#
+# James Macnicol
+#
+#-----------------------------------------------------------------------------
+
+# Version number and date information
+
+# NOTE THAT MY E-MAIL ADDRESS HAS CHANGED (AS OF VERSION 0.6.1) !!!!
+
+$version = "0.6.1";
+$versiondate = "11th February 1998";
+$emailaddress = "james.macnicol\@mailexcite.com";
+$copyright = "Copyright (C) 1996-1998 James Macnicol ($emailaddress)";
+
+#
+# Map identifying strings in /Notice into foundry names. Separate identifier
+# from name with a :. Someone let me know if this is a problem (i.e. foundry
+# has a : in its name which really ought to be there (although I may not
+# believe it) ; we'll change it to ! or something.
+#
+# You probably want to put foundries which license type from others near the
+# top of this list (e.g. Adobe). If the name of the original source of the
+# face is listed lower down then it will be used that instead. It's just that
+# Adobe does have its own faces too, but more often than not they are
+# licensed. Doing it this way will make it work out correctly in either case.
+#
+
+
+@foundries = (
+ "Adobe:adobe",
+ "Allied Corporation:allied",
+ "Publishers' Paradise:paradise",
+ "PUBLISHERS' PARADISE:paradise",
+ "Bigelow & Holmes:b&h",
+ "Bitstream:bitstream",
+ "Corel Corporation:corel",
+ "International Typeface Corporation:itc",
+ "IBM:ibm",
+ "LETRASET:letraset",
+ "Monotype Corporation:monotype",
+ "SoftMaker:softmaker",
+ "URW:urw",
+ "Jonathan Brecher:brecher",
+ "Brendel Informatik:brendel",
+ "A. Carr:carr",
+ "FontBank:fontbank",
+ "Hershey:hershey",
+ "A.S.Meit:meit",
+ "Andrew s. Meit:meit",
+ "S.G. Moye:moye",
+ "S. G. Moye:moye",
+ "D. Rakowski:rakowski",
+ "David Rakowski:rakowski",
+ "Reasonable Solutions:reasonable",
+ "Southern Software:southern",
+ "Title Wave:titlewave",
+ "ZSoft:zsoft",
+ "Digiteyes Multimedia:digiteyes",
+ "MWSoft:mwsoft",
+ "MacroMind:macromind",
+ "Three Islands Press:3ip",
+ "Hank Gillette:gillette",
+ "Doug Miles:miles",
+ "Richard Mitchell:mitchell");
+
+# Note: Hershey is the public Hershey fonts which come with Ghostscript.
+# These cause no end of problems since they look inside like funny PS
+# programs rather than standard fonts. The current version of type1inst will
+# refuse to process such fonts. Older versions (< 0.6) tended to fall over
+# when these were present.
+
+# Note 2 : Some of these are obviously names of people only, not companies.
+# They are generally public domain fonts.
+
+# Note 3 : Publisher's Paradise did not produce a majority of the fonts that
+# contain their name in the /Notice field, rather they distributed them on
+# their BBS. Unfortunately there is no other identifying info in these fonts.
+
+#
+# These are font weights. Some are synonyms, e.g. regular for medium. It
+# has been suggested we map "thin" to "light", however there are some font
+# families which have both "thin" and "light" variants. An example is
+# Linotype's Helvetica Neue. Please let me know if you find a font where
+# assuming "semi", and "demi" to be the same fails.
+#
+
+@weights = (
+ "book:book",
+ "demibold:demibold",
+ "semibold:demibold",
+ "demi:demibold",
+ "semi:demibold",
+ "extrabold:extrabold",
+ "boldface:bold",
+ "bold:bold",
+ "heavyface:heavyface",
+ "heavy:heavy",
+ "ultrablack:ultrablack",
+ "extrablack:extrablack",
+ "ultra:ultra", # it's gonna break some widths...
+ "black:black",
+ "extralight:extralight",
+ "light:light",
+ "thin:thin",
+ "super:super",
+ "thin:thin",
+ "light:light",
+ "semi:demi",
+ "bold:bold",
+ "heavy:heavy",
+ "black:black",
+ "normal:medium",
+ "regular:regular",
+ "roman:regular" # this too might break something...
+ );
+
+#
+# Likewise for slants
+#
+
+@slants = (
+ "italic:i",
+ "roman:r",
+ "regular:r",
+ # "it:i",
+ "cursive:i",
+ "kursiv:i",
+ "oblique:o",
+ "obl:o",
+ "slanted:o",
+ # Cyrillic fonts
+ "upright:r",
+ "inclined:i");
+
+#
+# Style. Wondering if we should put "serif" in here somehow....?
+#
+# I haven't put "ultracondensed" here since I think they're two different
+# things, i.e. Garamond Ultra Condensed is very bold but condensed.
+
+@styles = (
+ "extracondensed:extracondensed",
+ "condensed:condensed",
+ "cond:condensed",
+ "sans:sans",
+ "wide:wide",
+ "cn:condensed",
+ "narrow:narrow",
+ "extracompressed:extracompressed",
+ "compressed:compressed",
+ "extraextended:extraextended",
+ "extended:extended",
+ "expanded:expanded",
+ "normal:normal");
+
+#
+# Additional styles. Refer to the line that puts together $xline.
+#
+
+@addstyles = ("alt:alternate",
+ "beginning:beginning",
+ "display:display",
+ "dfr:dfr",
+ "ending:ending",
+ # "exp" and "ep" seems to be sometimes part of a fonts name,
+ # sometimes part of additional classification. I'm crying... :-(
+ "ep:expert",
+ "exp:expert",
+ "ornaments:ornaments",
+ "osf:oldstylefigures",
+ "outline:outline",
+ "sc:smallcaps",
+ "shaded:shaded",
+ "shadowed:shadowed",
+ "stencil:stencil",
+ "swash:swash",
+ "sw:swash",
+ "one:one",
+ "two:two",
+ "three:three",
+ "four:four",
+ # Some fonts use just "a" to mean a font with alternate
+ # character set.
+ "a:alternate");
+
+#
+# Write a message to the stdout and/or the log file depending on what the
+# user chose.
+#
+
+sub log_msg {
+ ($msg) = @_;
+
+ if (! $silent) {
+ print STDOUT "$msg";
+ }
+ if ($dologfile) {
+ print LOG "$msg";
+ }
+}
+
+sub log_only_msg {
+ ($msg) = @_;
+
+ if ($dologfile) {
+ print LOG "$msg";
+ }
+}
+
+#
+# Die with a bug message
+#
+
+sub die_bug {
+ ($msg) = @_;
+
+ die("BUG: $msg\nIf you have not modified the script in a way which might have\ncaused this error you are encouraged to report it as a bug to\n\n$emailaddress\n\n");
+}
+
+#
+# Print out a string with a given minimum width. This is used to make the
+# Fontmap entries look nice.
+#
+
+sub print_min_width {
+ ($stream, $minwidth, $string) = @_;
+ $_ = $string;
+ $strlength = length($string);
+ # Print the string
+ print $stream $string;
+ # Now pad out the rest of the space if the string is short.
+ if ($strlength < $minwidth) {
+ for ($i = 0; $i < ($minwidth - $strlength); $i = $i + 1) {
+ print $stream " ";
+ }
+ }
+}
+
+#
+# Indicate progress through the directory on the command line
+#
+
+sub print_progress {
+ $totalfonts = $numpffonts + $numgsfonts + $badfonts;
+ if (! $silent) {
+ if (($totalfonts % 10) == 0) {
+ print "[$totalfonts]\n";
+ }
+ }
+}
+
+#
+# Put the processing stuff into a procedure since we want to do the same for
+# .pfb, .pfa and .gsf files (once .pfb's are decompressed).
+#
+# Argument : filename.
+# Returns : X font description, name of font for Fontmap
+#
+
+sub process_font {
+ ($fname) = @_;
+ local($xline);
+
+ # Check to see if this is a ghostscript font
+ if ($fname =~ /\.gsf\s*$/) {
+ $gsfont = 1;
+ } else {
+ $gsfont = 0;
+ }
+
+ # Default is not MultipleMaster
+ $mm = 0;
+
+ open(IN, $fname) || die "cannot open $file for reading";
+ # An unlikely name to check to see we get a fontname out of the file.
+ $fontname = "abcXYZ:!@#";
+ $foundry = "unknown";
+ $notice = "No notice given.";
+ while(<IN>) {
+ if (/\/isFixedPitch\s+(.+)\s+def\s*/) {
+ if ($1 =~ /true/) {
+ $fixedpitch = "m";
+ } else {
+ $fixedpitch = "p";
+ }
+ }
+
+ # I think that we should accept the manufacturers classification.
+ # Try to extract this from FontName only if it's missing.
+ # (It shouldn't. There are other reasons why this won't work, though.)
+ if (/\/FamilyName\s*\((.+)\)\s+readonly\s+def\s*/) {
+ $familyname = $1;
+
+ # Convert to lower case (because case is insignificant).
+ # Spaces are acceptable according to XLFD.
+ $familyname =~ tr/A-Z/a-z/;
+ }
+ # Previous applies to this also... This might make xfontsels list a
+ # a little cluttered, though. Perhaps it would be better to map it
+ # to standard strings like you do. It's named $weight_add because
+ # you already used $weight...
+ if (/\/Weight\s*\((.+)\)\s+readonly\s+def\s*/) {
+ $weight_add = $1;
+
+ # Convert to lower case. Spaces are acceptable according to XLFD?
+ # Remove for consistency (as there would be any left after my
+ # slaughtering).
+ $weight_add =~ tr/A-Z/a-z/;
+ $weight_add =~ s/\s*//g;
+
+ # Remember if it's a MultipleMaster font
+ $mm = 1 if ($weight_add =~ /^all$/);
+ # Strange. This field seems to contain also width sometimes... remove it.
+ $numstyles = @styles;
+ for ($x = 0; $x < $numstyles; $x = $x + 1) {
+ $ident = $styles[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The style identification \"$ident\" is bad\n");
+ }
+ # Remove matched word from the font's name
+ $weight_add =~ s/$fields[0]//;
+ }
+ }
+ # FullName might contain useful information in determining
+ # the properties of a font.
+ if (/\/FullName\s*\((.+)\)\s+readonly\s+def\s*/) {
+ $fullname = $1;
+
+ # Convert to lower case
+ $fullname =~ tr/A-Z/a-z/;
+
+ # Some names got extra numerical information at the start.
+ $fullname =~ s/^\d*\s*(.+)/$1/;
+ }
+ # Note : some fonts have a suspect /FontName declaration where there
+ # is no space between /FontName and the name of the font itself....
+ if (/\/FontName\s*[\/\(]([^\)]+)\)?\s+def\s*/) {
+ $fontname = $1;
+
+ # Remove any embedded spaces
+ # (Probably unnecessary. If I remember it right, it can't contain any spaces,
+ # because it's a PostScript identifier/keyword or what's the right term...)
+ $fontname =~ s/\s//g;
+
+ # Save a copy of original full name for later
+ $fontnamecopy = $fontname;
+
+ # Convert to lower case
+ $fontname =~ tr/A-Z/a-z/;
+
+ # There are fonts like Mendoza Roman, Baskerville Book etc, where what
+ # looks like weight is part of the font's name, not it's weight.
+ # Split the name into fontname and fontstyle instead and handle them separate.
+ ($fontname, $fontstyle) = split(/-/, $fontname);
+
+ # Remove -s
+ $fontname =~ s/-//g;
+ $fontstyle =~ s/-//g;
+
+
+ # Check for weight modifiers (medium, bold, demi, light etc.)
+ $weight = "medium";
+ $numweights = @weights;
+ for ($x = 0; $x < $numweights; $x = $x + 1) {
+ $ident = $weights[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The weight identification \"$ident\" is bad\n");
+ }
+ if ($fontstyle =~ /$fields[0]/) {
+ $weight = $fields[1];
+ } elsif ($weight_add) {
+ # Try any possible way
+ $weight = $weight_add;
+ }
+ # Remove matched word from the font's name
+ $fontstyle =~ s/$fields[0]//;
+ }
+
+ # Check for slant (italic, roman, oblique)
+ $slant = "r";
+
+ $numslants = @slants;
+ for ($x = 0; $x < $numslants; $x = $x + 1) {
+ $ident = $slants[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The slant identification \"$ident\" is bad\n");
+ }
+ if ($fontstyle =~ /$fields[0]/) {
+ $slant = $fields[1];
+ }
+ # Remove matched word from the font's name
+ $fontstyle =~ s/$fields[0]//;
+ }
+
+ # Check for style (condensed, normal, sans, or wide)
+ $style = "normal";
+
+ $numstyles = @styles;
+ for ($x = 0; $x < $numstyles; $x = $x + 1) {
+ $ident = $styles[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The style identification \"$ident\" is bad\n");
+ }
+ if ($fontstyle =~ /$fields[0]/) {
+ $style = $fields[1];
+ }
+ # Remove matched word from the font's name
+ $fontstyle =~ s/$fields[0]//;
+ }
+
+ # Check for additional styles (alternate, smallcaps, oldstylefigures etc.)
+ $addstyle = "";
+
+ $numaddstyles = @addstyles;
+ for ($x = 0; $x < $numaddstyles; $x = $x + 1) {
+ $ident = $addstyles[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The additional style identification \"$ident\" is bad.\n");
+ }
+ if ($fontstyle =~ /$fields[0]/) {
+ $addstyle = $fields[1];
+ }
+ # Remove matched word from the font's name
+ $fontstyle =~ s/$fields[0]//;
+ }
+ }
+ if (/^\/Encoding\s+(\S+)\s*/) {
+ if ($1 =~ /StandardEncoding/) {
+ $encoding = "iso8859-1";
+ } else {
+ # This needs work
+ $encoding = "adobe-fontspecific";
+ }
+ }
+
+ if (/^\s*\/Notice\s*(.*)$/) {
+ $notice = $1;
+
+ $notice =~ s/readonly def//g;
+
+ $numfoundries = @foundries;
+ for ($x = 0; $x < $numfoundries; $x = $x + 1) {
+ $ident = $foundries[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The foundry identification \"$ident\" is bad.\n");
+ }
+ if ($notice =~ /$fields[0]/) {
+ $foundry = $fields[1];
+ }
+ }
+ }
+
+ # MultipleMaster fonts have this field.
+ if (/\/BlendAxisTypes\s+\[([^\]]+)\]\s*def/) {
+ $axis = $1;
+ # Remove axises we don't need
+ $axis =~ s/\/Weight\s+//;
+ $axis =~ s/\/Width\s+//;
+ # Are there still some axises left?
+ if ($axis =~ /\//) {
+ # Remove trailing spaces
+ $axis =~ s/^(.*?)\s*$/$1/;
+ $axis =~ s/\/\S+/0/g;
+ $axis= "[$axis]";
+ }
+ }
+
+ # Break out of loop if we've passed the interesting stuff.
+ # And time to try another way to find out the fontname.
+ if ((! $gsfont) && (/currentfile\s+eexec/)) {
+ &try_another_way();
+ # This is for .pfa and .pfb fonts
+ last;
+ } elsif (($gsfont) && (/currentdict\s+end/)) {
+ &try_another_way();
+ # This is for ghostscript .gsf fonts. Why don't all these have a
+ # currentfile eexec ?
+ last;
+ }
+ }
+ close(IN);
+
+ # I use quite different mechanism to get fontname etc. However it's done,
+ # the results are hard to get right. Should it be a command-line option?
+ # Now I try both ways.
+
+ # familyname, use fontname
+ $familyname = ($anotherway ? $familyname : $fontname);
+
+ # Oh, we are dealing with a MultipleMaster font...
+ if ($mm) {
+ $weight = "0";
+ $style = "0";
+ $addstyle .= $axis;
+ }
+
+ if ($familyname =~ /abcXYZ\:\!\@\#/) {
+ log_only_msg("\n");
+ log_only_msg("$filename : could not determine font name\n");
+ log_only_msg("\n");
+ $badfonts = $badfonts + 1;
+ &print_progress();
+ return;
+ }
+
+ if (($dox) && (! $gsfont) && ($foundry =~ /unknown/)) {
+ $nofoundry = $nofoundry + 1;
+ log_only_msg("\n");
+ log_only_msg("$filename ($fontnamecopy) : foundry not matched\n");
+ log_only_msg(" /Notice said : \"$notice\"\n");
+ log_only_msg("\n");
+ } elsif ($dox) {
+# log_only_msg("$filename ($fontnamecopy) : okay\n");
+ }
+
+ if (($dox) && (! $gsfont)) {
+ # Addstyle is any extra information needed to uniquely identify a variation of a font
+ # in it's family, like "alternate" (ACaslon-AltRegular) or "one" (EuropeanPi-One).
+ # Changed fontname to familyname because it describes that field better, but that's
+ # just my opinion...
+ $xline = "-$foundry-$familyname-$weight-$slant-$style-$addstyle-0-0-0-0-$fixedpitch-0-$encoding";
+ }
+
+ # Update count of each type
+ if ($gsfont) {
+ $numgsfonts = $numgsfonts + 1;
+ } else {
+ $numpffonts = $numpffonts + 1;
+ }
+
+ &print_progress();
+
+ ($xline, $fontnamecopy);
+}
+
+
+#
+# An alternative way to get fontname
+#
+
+sub try_another_way {
+ # Strip familyname from fullname. This seems to work most of time.
+ # Some fontnames have extra numerical information after familyname.
+ # Strip it if it's longer than two numbers.
+ # Otherwise, it's probably part of additional style classification.
+ # In a few cases it IS part of the name, and this algorithm should break.
+ # Sometimes there's a strange string of *'s somewhere. Get rid of it.
+ $fullname =~ s/\*//g;
+ print STDERR "1: ${fullname}:\n" if $debug;
+ if ($fullname =~ s/^$familyname\s*(\d\d+)?\s*(.*)/$2/) {
+ # Wow. It worked. Let's continue and remove excess whitespace.
+ $anotherway = 1;
+ $fullname =~ s/\s+//g;
+
+ # familyname can now stripped of -s
+ $familyname =~ s/-//g; # Or space?
+ print STDERR "2: ${fullname}:\n" if $debug;
+
+ # Check for weight modifiers (medium, bold, demi, light etc.)
+ $weight = "medium";
+ $numweights = @weights;
+ for ($x = 0; $x < $numweights; $x = $x + 1) {
+ $ident = $weights[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The weight identification \"$ident\" is bad\n");
+ }
+ if ($fullname =~ /$fields[0]/) {
+ $weight = $fields[1];
+ $weight =~ s/-//g;
+ }
+ # Remove matched word from the font's name
+ $fullname =~ s/$fields[0]//;
+ }
+
+ print STDERR "3: ${fullname}:\n" if $debug;
+
+ # Check for slant (italic, oblique)
+ $slant = "r";
+
+ $numslants = @slants;
+ for ($x = 0; $x < $numslants; $x = $x + 1) {
+ $ident = $slants[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The slant identification \"$ident\" is bad\n");
+ }
+ if ($fullname =~ /$fields[0]/) {
+ $slant = $fields[1];
+ $slant =~ s/-//g;
+ }
+ # Remove matched word from the font's name
+ $fullname =~ s/$fields[0]//;
+ }
+ print STDERR "4: ${fullname}:\n" if $debug;
+ # Check for style (normal or sans)
+ $style = "normal";
+
+ $numstyles = @styles;
+ for ($x = 0; $x < $numstyles; $x = $x + 1) {
+ $ident = $styles[$x];
+ @fields = split(/:/, $ident);
+ $numfields = @fields;
+ if ($numfields != 2) {
+ die_bug("The style identification \"$ident\" is bad\n");
+ }
+ if ($fullname =~ /$fields[0]/) {
+ $style = $fields[1];
+ $style =~ s/-//g;
+ }
+ # Remove matched word from the font's name
+ $fullname =~ s/$fields[0]//;
+ }
+
+ # What's left of fullname is probably additional style information.
+ # Some fontnames have some strange numerical information here too.
+ # If it's just one number, it usually refers to some variant of the
+ # fontfamily, otherwise, just get rid of it.
+ $fullname = "" if ($fullname =~ /^\d\d+$/);
+ print STDERR "5: ${fullname}:\n" if $debug;
+ $addstyle = $fullname;
+ $addstyle =~ s/-//g;
+ } else {
+ $anotherway = 0;
+ }
+}
+
+#
+# Makes associative array out of current entries in fonts.scale
+#
+
+sub read_fonts_scale {
+ local($finish, %rv, $line, $filename, $fontname);
+
+ $finish = open(SCALE, "fonts.scale") ? 0 : 1;
+ if ($finish == 1) {
+ %rv;
+ }
+
+ log_only_msg("Reading fonts.scale ....");
+
+ # First line should be an integer saying how many fonts there are.
+ # Discard.
+ $line = <SCALE>;
+ if (! $line =~ /\s*[0-9]+\s*/) {
+ log_only_msg("Warning : first line of fonts.scale is bad\n");
+ }
+
+ while (<SCALE>) {
+ # Very rough pattern
+ if (/\s*(\S+)\s+(.+)\s*/) {
+ chop;
+ $filename = $1;
+ $fontname = $2;
+ if (! -e $filename) {
+ $numxremoved++;
+ log_only_msg("Removed fonts.scale entry \"$_\" since the file did not exist\n");
+ next;
+ }
+ if ($rv{$filename}) {
+ $numxduplicates++;
+ log_only_msg("Warning : fonts.scale already contains a line for file \"$filename\"\n");
+ log_only_msg(" the line \"$_\" has been ignored\n");
+ } else {
+ $rv{$filename} = $fontname;
+ }
+ } else {
+ log_only_msg(" Couldn't understand line : \n");
+ log_only_msg(" \"$_\"\n");
+ }
+ }
+ close(SCALE);
+
+ log_only_msg("Done.\n");
+
+ %rv;
+}
+
+#
+# Write out an associative array into fonts.scale, making a backup copy
+# first.
+#
+
+sub write_fonts_scale {
+ (%fontdata) = @_;
+ local($numentries, $key);
+
+ # First, make backup copy
+ if (-e "fonts.scale") {
+ system ("cp -f fonts.scale fonts.scale.bak");
+ }
+
+ log_only_msg("Writing fonts.scale....\n");
+
+ $numentries = keys(%fontdata);
+ open(SCALE, ">fonts.scale") || die("Can't open fonts.scale!\n");
+ print SCALE "$numentries\n";
+ foreach $key (sort(keys %fontdata)) {
+ print_min_width(SCALE, 12, $key);
+ print SCALE " ";
+ print SCALE "$fontdata{$key}\n";
+ }
+ close(SCALE);
+ system ("chmod 0755 fonts.scale") && log_msg("Coudln't chmod \"fonts.scale\" ... continuing on anyway\n");
+
+ log_only_msg(" Done.\n");
+}
+
+#
+# Read the current Fontmap and return associative array with data.
+#
+
+sub read_fontmap {
+ local(%rv, $finish, $fontname, $filename);
+
+ $finish = open(FONTMAP, "Fontmap") ? 0 : 1;
+ if ($finish) {
+ %rv;
+ }
+
+ log_only_msg("Reading Fontmap ....\n");
+
+ while (<FONTMAP>) {
+ if (/\/+(\S+)\s+\((.*)\)\s+;\s+/) {
+ chop;
+ $fontname = $1;
+ $filename = $2;
+ if (! -e $filename) {
+ $numgsremoved++;
+ log_only_msg("Removed Fontmap entry \"$_\" since the file did not exist\n");
+ next;
+ }
+ if ($rv{$filename}) {
+ # Entry already exists
+ $numgsduplicates++;
+ log_only_msg("Warning : the Fontmap already contains a line for file \"$filename\"\n");
+ log_only_msg(" the line \"$_\" has been ignored\n");
+ } else {
+ $rv{$filename} = $fontname;
+ }
+ } else {
+ $numgsbarf++;
+ log_only_msg("Couldn't understand line :\n");
+ log_only_msg(" $_\n");
+ }
+ }
+
+ close(FONTMAP);
+
+ log_only_msg("Done.\n");
+
+ %rv;
+}
+
+#
+# Write associative array containing font data to Fontmap
+#
+
+sub write_fontmap {
+ (%fontdata) = @_;
+ local($numentries, $key);
+
+ # First, make backup copy
+ if (-e "Fontmap") {
+ system ("cp -f Fontmap Fontmap.bak");
+ }
+
+ log_only_msg("Writing Fontmap....");
+
+ $numentries = keys(%fontdata);
+ open(FONTMAP, ">Fontmap") || die("Couldn't open Fontmap!\n");
+ foreach $key (sort(keys %fontdata)) {
+ print_min_width(FONTMAP, 40, "/$fontdata{$key}");
+ print FONTMAP " ";
+ print FONTMAP "($key)\t;\n";
+ }
+ close(FONTMAP);
+ system ("chmod 0755 Fontmap") && log_msg("Couldn't chmod \"Fontmap\" ... continuing on anyway\n");
+
+ log_only_msg(" Done.\n");
+}
+
+#
+# Add a font (either X or gs) to hash table
+#
+
+sub add_font_to_aarray {
+ ($fname, $text, %aa) = @_;
+
+ if (($text =~ /^\s*$/) || ($fname =~ /^\s*$/)) {
+ # This will occur if the font is a dud (e.g. a Hershey font). We
+ # assume that $badfonts has been incremented and we just return.
+ %aa;
+ }
+
+ if (! $aa{$fname}) {
+ $aa{$fname} = $text;
+ }
+
+ %aa;
+}
+
+#
+# Create sample text using each font
+#
+
+sub font_sample {
+ ($filename, $fontname, $height) = @_;
+ local($text, $alltext, $samplefile);
+
+ if (($filename =~ /^\s*$/) || ($fontname =~ /^s*$/)) {
+ print "font_sample: $filename, $fontname\n";
+ die_bug("Bad argument(s) to font_sample()!\n");
+ }
+
+# Here we create a full page sample for the current font. It contains
+# a large point-size version, a normal sized version, and a small version.
+
+ $text = <<"TEXT";
+%!
+%%EndComments
+/$samplefont findfont
+18 scalefont
+setfont
+newpath
+200 715 moveto
+(File : $filename) show
+200 695 moveto
+(Font Name : $fontname) show
+% t1embed : $filename $fontname
+closepath
+
+/$fontname findfont
+60 scalefont
+setfont
+newpath
+40 640 moveto
+(ABCDE) show
+40 575 moveto
+(FGHIJK) show
+40 510 moveto
+(LMNOP) show
+40 445 moveto
+(QRSTU) show
+40 380 moveto
+(VWXYZ) show
+40 305 moveto
+(abcdefghijklm) show
+40 240 moveto
+(nopqrstuvwxyz) show
+40 175 moveto
+(1234567890) show
+closepath
+
+/$fontname findfont
+12 scalefont
+setfont
+newpath
+50 148 moveto
+(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) show
+50 132 moveto
+(a b c d e f g h i j k l m n o p q r s t u v w x y z) show
+50 116 moveto
+(1 2 3 4 5 6 7 8 9 0 \! \$ \% \& \\\( \\\) \; \: \< \> ) show
+closepath
+
+/$fontname findfont
+4 scalefont
+setfont
+newpath
+50 99 moveto
+(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) show
+50 93 moveto
+(a b c d e f g h i j k l m n o p q r s t u v w x y z) show
+50 87 moveto
+(1 2 3 4 5 6 7 8 9 0 \! \$ \% \& \\\( \\\) \; \: \< \> ) show
+closepath
+showpage
+TEXT
+
+ $samplefile = $fontname . ".ps";
+ open(SAMPLE, ">samples/$samplefile") ||
+ die("Couldn't open samples/$samplefile\n");
+ print SAMPLE "$text\n";
+ close(SAMPLE);
+ system("chmod 0755 samples/$samplefile") && log_msg("Couldn't chmod individual sample file \"samples/$samplefile\" ... continuing on anyway\n");
+
+# For the "allfont.ps" files we use a standard font for the font name so
+# that in the case of non-alpha fonts we still can still read the name of
+# the font (eg symbol or dingbats).
+
+ if ($height == 700) {
+ $allsample = "samples/allfont-$allcount.ps";
+ $allcount = $allcount + 1;
+
+ log_only_msg("Creating new sample file \"$allsample\"....");
+ open(ALLSAMPLE, ">$allsample") ||
+ die("Couldn't open $allsample\n");
+ log_only_msg("done\n");
+ print ALLSAMPLE "%!\n";
+ print ALLSAMPLE "%%EndComments\n";
+ }
+
+ $alltext = <<"ALLTEXT";
+
+% t1embed : $filename $fontname
+/$samplefont findfont
+12 scalefont
+setfont
+newpath
+30 $height moveto
+($fontname : ) show
+/$fontname findfont
+20 scalefont
+setfont
+(AbCdEfGhIjKlMnOpQrStUvWxYz 0123456789) show
+closepath
+ALLTEXT
+
+ print ALLSAMPLE "$alltext\n";
+ $height = $height - 32;
+ if ($height < 100) {
+ print ALLSAMPLE "showpage\n";
+ close(ALLSAMPLE);
+ system("chmod 0755 $allsample") && log_msg("Couldn't chmod all sample sheet \"$allsample\" ... continuing on anyway\n");
+ $height = 700;
+ }
+
+ ($height);
+}
+
+#
+# Some users have had problems with perl's file globbing not working. This
+# gets a shell to do it for us. It matches all files with the extension
+# specified in the parameter, i.e. if pat = "foo" then it matches all of
+# *.foo .
+#
+
+sub do_glob {
+ ($pat) = @_;
+ local($raw, @fnames);
+ open(SHELL, "echo *.$pat|") || die("Couldn't open shell in do_glob\n");
+ $raw = <SHELL>;
+ $raw =~ s/\*\.$pat//;
+ @fnames = split(/\s/,$raw);
+ close(SHELL);
+ (@fnames);
+}
+
+# ------------------------------------------------------------------------
+# Start of program proper
+# ------------------------------------------------------------------------
+
+# Process command line arguments
+$workdir = 0;
+$dox = 1;
+$dogs = 1;
+$silent = 0;
+$samples = 0;
+$dologfile = 1;
+@argvcopy = (@ARGV);
+$numargs = @ARGV;
+for ($x = 0; $x < $numargs; $x = $x + 1) {
+ $arg = $ARGV[$x];
+ if ($arg =~ /-nox/) {
+ $dox = 0;
+ } elsif ($arg =~ /-nogs/) {
+ $dogs = 0;
+ } elsif ($arg =~ /-silent/) {
+ $silent = 1;
+ } elsif ($arg =~ /-quiet/) {
+ $silent = 1;
+ } elsif ($arg =~ /-q/) {
+ $silent = 1;
+ } elsif ($arg =~ /-samples/) {
+ $samples = 1;
+ } elsif ($arg =~ /-nolog/) {
+ $dologfile = 0;
+ } elsif ($arg =~ /-d/) {
+ $x++;
+ $workdir = $ARGV[$x];
+ } elsif ($arg =~ /-version/) {
+ die("type1inst version $version ($versiondate)\n$copyright\n");
+ } elsif ($arg =~ /-v/) {
+ die("type1inst version $version ($versiondate)\n$copyright\n");
+ } else {
+ die("Usage: $0 [-silent] [-quiet] [-q] [-nox] [-nogs] [-samples] [-version] [-v]\n");
+ }
+}
+if ((! $dox) && (! $dogs) && (! $samples)) {
+ die("$0: Nothing to do!\n");
+}
+
+if ($workdir) {
+ chdir $workdir || die "Cannot change to \"$workdir\"";
+}
+
+# Open logfile
+if ($dologfile) {
+ open(LOG, ">type1inst.log") || die "Cannot open log file \"type1inst.log\"";
+}
+
+log_only_msg("type1inst Version $version ($versiondate)\n");
+log_only_msg("$copyright\n\n");
+open (DATE, "date|") || die("Couldn't run \"date\"\n");
+$currenttime = <DATE>;
+log_only_msg("Run started at $currenttime\n");
+close(DATE);
+
+# Setup directory for font samples
+if ($samples) {
+ if (! -e "samples") {
+ # Create directory for sample text PS files
+ log_only_msg("Creating directory for samples ...\n");
+ system("mkdir samples");
+ system("chmod 0755 samples") && log_msg("Coudln't chmod \"samples\" directory\n");
+
+ } elsif (-f "samples") {
+ die("$0: remove file \"samples\" or do not use -samples option\n");
+ } else {
+ log_msg("Clearing samples directory\n");
+ system("rm -f samples/*.ps");
+ }
+ $height = 700;
+ $samplefont = "Helvetica";
+ $allcount = 0;
+ $allsample = "samples/allfont-$allcount.ps";
+ log_only_msg("Creating new sample file \"$allsample\"....");
+ open(ALLSAMPLE, ">$allsample") || die("Couldn't open all sample file \"$allsample\"\n");
+ log_only_msg("done\n");
+ print ALLSAMPLE "%!\n";
+ print ALLSAMPLE "%%EndComments\n";
+}
+
+
+# Counts how many fonts we come across
+$numpffonts = 0;
+$numgsfonts = 0;
+$nofoundry = 0;
+$badfonts = 0;
+$numskipped = 0;
+$numxremoved = 0;
+$numgsremoved = 0;
+$numxduplicates = 0;
+$numgsduplicates = 0;
+$numxbarf = 0;
+$numgsbarf = 0;
+
+if (! $silent) {
+ print "type1inst Version $version ($versiondate)\n";
+ print "$copyright\n\n";
+}
+
+$totalfonts = 0;
+foreach $filename (do_glob("pfa")) {
+ $totalfonts++;
+}
+foreach $filename (do_glob("pfb")) {
+ $totalfonts++;
+}
+foreach $filename (do_glob("pfa.gz")) {
+ $totalfonts++;
+}
+foreach $filename (do_glob("pfb.gz")) {
+ $totalfonts++;
+}
+foreach $filename (do_glob("gsf")) {
+ $totalfonts++;
+}
+if (! $silent) {
+ if ($totalfonts == 0) {
+ die("There are no PostScript fonts in this directory\n");
+ } elsif ($totalfonts == 1) {
+ print "There is 1 PostScript font in this directory\n";
+ } else {
+ print "There are a total of $totalfonts PostScript fonts in this directory\n";
+ }
+}
+
+if ($dox) {
+ %fs = &read_fonts_scale();
+}
+if (($dogs) || ($samples)) {
+ %fm = &read_fontmap();
+}
+
+# Process ASCII PS fonts
+foreach $filename (do_glob("pfa")) {
+ if (($dox && (! $fs{$filename})) ||
+ (($dogs || $samples) && (! $fm{$filename}))) {
+ ($x, $gs) = &process_font($filename);
+ if ($dox) {
+ %fs = &add_font_to_aarray($filename, $x, %fs);
+ }
+ if (($dogs) || ($samples)) {
+ %fm = &add_font_to_aarray($filename, $gs, %fm);
+ }
+ } else {
+ $numpffonts = $numpffonts + 1;
+ $numskipped = $numskipped + 1;
+ &print_progress();
+ }
+ if ($samples) {
+ ($height) = &font_sample($filename, $fm{$filename}, $height);
+ }
+}
+
+# Process binary PS fonts
+foreach $filename (do_glob("pfb")) {
+ if (($dox && (! $fs{$filename})) ||
+ (($dogs || $samples) && (! $fm{$filename}))) {
+ system("pfbtops $filename > foo");
+ ($x, $gs) = &process_font("foo");
+ system("rm foo");
+ if ($dox) {
+ %fs = &add_font_to_aarray($filename, $x, %fs);
+ }
+ if ($dogs || $samples) {
+ %fm = &add_font_to_aarray($filename, $gs, %fm);
+ }
+ } else {
+ $numpffonts = $numpffonts + 1;
+ $numskipped = $numskipped + 1;
+ &print_progress();
+ }
+ if ($samples) {
+ ($height) = &font_sample($filename, $fm{$filename}, $height);
+ }
+}
+
+# Process binary PS fonts
+foreach $filename (do_glob("pfa.gz")) {
+ if (($dox && (! $fs{$filename})) ||
+ (($dogs || $samples) && (! $fm{$filename}))) {
+ system("gunzip -c $filename > foo");
+ ($x, $gs) = &process_font("foo");
+ system("rm foo");
+ if ($dox) {
+ %fs = &add_font_to_aarray($filename, $x, %fs);
+ }
+ if ($dogs || $samples) {
+ %fm = &add_font_to_aarray($filename, $gs, %fm);
+ }
+ } else {
+ $numpffonts = $numpffonts + 1;
+ $numskipped = $numskipped + 1;
+ &print_progress();
+ }
+ if ($samples) {
+ ($height) = &font_sample($filename, $fm{$filename}, $height);
+ }
+}
+
+# Process binary PS fonts
+foreach $filename (do_glob("pfb.gz")) {
+ if (($dox && (! $fs{$filename})) ||
+ (($dogs || $samples) && (! $fm{$filename}))) {
+ system("gunzip -c $filename | pfbtops > foo");
+ ($x, $gs) = &process_font("foo");
+ system("rm foo");
+ if ($dox) {
+ %fs = &add_font_to_aarray($filename, $x, %fs);
+ }
+ if ($dogs || $samples) {
+ %fm = &add_font_to_aarray($filename, $gs, %fm);
+ }
+ } else {
+ $numpffonts = $numpffonts + 1;
+ $numskipped = $numskipped + 1;
+ &print_progress();
+ }
+ if ($samples) {
+ ($height) = &font_sample($filename, $fm{$filename}, $height);
+ }
+}
+
+# Process Ghostscript fonts
+if ($dogs || $samples) {
+ foreach $filename (do_glob("gsf")) {
+ if (! $fm{$filename}) {
+ ($x, $gs) = &process_font($filename);
+ %fm = &add_font_to_aarray($filename, $gs, %fm);
+ } else {
+ $numgsfonts = $numgsfonts + 1;
+ $numskipped = $numskipped + 1;
+ &print_progress();
+ }
+ if ($samples) {
+ ($height) = &font_sample($filename, $fm{$filename}, $height);
+ }
+ }
+}
+
+if ($dox) {
+ &write_fonts_scale(%fs);
+ system("mkfontdir"); # Generate fonts.dir
+ system("chmod 0755 fonts.dir") && log_msg("Couldn't chmod \"fonts.dir\" ... continuing on anyway\n");
+}
+if ($dogs) {
+ &write_fontmap(%fm);
+}
+
+# Finish up the all font sample file
+if ($samples) {
+ log_only_msg("Finished font sample files\n");
+ if ($height < 700) {
+ print ALLSAMPLE "showpage\n";
+ close(ALLSAMPLE);
+ system("chmod 0755 $allsample") && log_msg("Couldn't chmod \"$allsample\" ... continuing on anyway\n");
+ }
+}
+
+# Report
+if (! $silent) {
+ $totalfonts = $numpffonts + $numgsfonts + $badfonts;
+
+ # List statistics
+ print "-------------------------------------------------------\n";
+ if ($totalfonts == 0) {
+ print "No fonts were found in this directory\n";
+ } elsif ($totalfonts == 1) {
+ print "1 font was found in this directory\n";
+ } else {
+ print "$totalfonts fonts found\n";
+ }
+ if ($numpffonts == 1) {
+ print "1 was a PostScript font\n";
+ } elsif ($numpffonts > 1) {
+ print "$numpffonts were standard PostScript fonts\n";
+ }
+ if ($numgsfonts == 1) {
+ print "1 was a Ghostscript font\n";
+ } elsif ($numgsfonts > 1) {
+ print "$numgsfonts were Ghostscript fonts\n";
+ }
+ if ($numskipped == 1) {
+ print "\n";
+ print "I skipped one of these fonts because it already had\n";
+ print "an overriding entry in both fonts.scale and/or Fontmap\n";
+ print "(X Windows font or Ghostscript font respectively).\n";
+ } elsif ($numskipped > 1) {
+ print "\n";
+ print "I skipped $numskipped of these fonts because they already\n";
+ print "had overriding entries in both fonts.scale and/or Fontmap\n";
+ print "(X Windows fonts or Ghostscript fonts respectively).\n";
+ }
+
+ # Print error messages
+ $wereerrors = 0;
+ if ($badfonts > 0) {
+ $wereerrors = 1;
+ print "-------------------------------------------------------\n";
+ if ($badfonts == 1) {
+ print "I couldn't extract a font name for 1 font in\n";
+ } else {
+ print "I couldn't extract font names for $ badfonts fonts in\n";
+ }
+ print "this directory. This means the font file had a non-standard\n";
+ print "format which this program doesn't know about or cannot do\n";
+ print "anything with. Check the README file to find out more.\n";
+ }
+ if ($dox) {
+ if ($nofoundry > 0) {
+ $wereerrors = 1;
+ print "-------------------------------------------------------\n";
+ print "For $nofoundry of these I couldn't figure out which foundry\n";
+ print "the font is from. Thus, these fonts will appear under the\n";
+ print "foundry unknown, i.e. X font name -unknown-*.\n";
+ print "Please consult the README file to see what this means.\n";
+ }
+
+ if ($numxremoved > 0) {
+ $wereerrors = 1;
+ print "-------------------------------------------------------\n";
+ if ($numxremoved == 1) {
+ print "While reading the existing fonts.scale file I saw 1 entry\n";
+ } else {
+ print "While reading the existing fonts.scale file I saw $numxremoved entries\n";
+ }
+ print "which mentioned a filename which now does not exist. Most likely\n";
+ print "you removed or renamed the file. I ignored these entries.\n";
+ }
+ if ($numxbarf > 0) {
+ $wereerrors = 1;
+ print "-------------------------------------------------------\n";
+ if ($numxbarf == 1) {
+ print "There was a line in fonts.scale I couldn't understand.\n";
+ } else {
+ print "There were $numxbarf lines in fonts.scale which I couldn't understand\n";
+ }
+ print "These were ignored.\n";
+ }
+ }
+ if ($dogs) {
+ if ($numgsremoved > 0) {
+ $wereerrors = 1;
+ print "-------------------------------------------------------\n";
+ if ($numgsremoved == 1) {
+ print "While reading the existing Fontmap file I saw 1 entry\n";
+ } else {
+ print "While reading the existing Fontmap file I saw $numgsremoved entries\n";
+ }
+ print "which mentioned a filename which now does not exist. Most likely\n";
+ print "you removed or renamed the file. I ignored these entries.\n";
+ }
+ if ($numgsbarf > 0) {
+ $wereerrors = 1;
+ print "-------------------------------------------------------\n";
+ if ($numgsbarf == 1) {
+ print "There was a line in Fontmap I couldn't understand.\n";
+ } else {
+ print "There were $numgsbarf lines in Fontmap which I couldn't understand\n";
+ }
+ print "These were ignored.\n";
+ }
+ }
+
+ if ($wereerrors) {
+ print "-------------------------------------------------------\n";
+ print "\n";
+ print "A log of errors is located in the file \"type1inst.log\"\n";
+ print "\n";
+ }
+}
diff --git a/knetworkconf/backends/util.pl.in b/knetworkconf/backends/util.pl.in
new file mode 100644
index 0000000..dea7036
--- /dev/null
+++ b/knetworkconf/backends/util.pl.in
@@ -0,0 +1,463 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# Utility functions.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Arturo Espinosa <arturo@ximian.com>
+# Michael Vogt <mvo@debian.org> - Debian 2.[2|3] support.
+# David Lee Ludwig <davidl@wpi.edu> - Debian 2.[2|3] support.
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+# --- Utilities for strings, arrays and other data structures --- #
+
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+sub gst_max
+{
+ return ($_[0] > $_[1])? $_[0]: $_[1];
+}
+
+# Boolean <-> strings conversion.
+
+sub gst_util_read_boolean
+{
+ my ($v) = @_;
+
+ return 1 if ($v =~ "true" ||
+ $v =~ "yes" ||
+ $v =~ "YES" ||
+ $v =~ "on" ||
+ $v eq "1");
+ return 0;
+}
+
+
+sub gst_print_boolean_yesno
+{
+ if ($_[0] == 1) { return "yes"; }
+ return "no";
+}
+
+
+sub gst_print_boolean_truefalse
+{
+ if ($_[0] == 1) { return "true"; }
+ return "false";
+}
+
+
+sub gst_print_boolean_onoff
+{
+ if ($_[0] == 1) { return "on"; }
+ return "off";
+}
+
+
+# Pushes a list to an array, only if it's not already in there.
+# I'm sure there's a smarter way to do this. Should only be used for small
+# lists, as it's O(N^2). Larger lists with unique members should use a hash.
+
+sub gst_push_unique
+{
+ my $arr = $_[0];
+ my $found;
+ my $i;
+
+ # Go through all elements in pushed list.
+
+ for ($i = 1; $_[$i]; $i++)
+ {
+ # Compare against all elements in destination array.
+
+ $found = "";
+ for $elem (@$arr)
+ {
+ if ($elem eq $_[$i]) { $found = $elem; last; }
+ }
+
+ if ($found eq "") { push (@$arr, $_[$i]); }
+ }
+}
+
+
+# Merges scr array into dest array.
+sub gst_arr_merge
+{
+ my ($dest, $src) = @_;
+ my (%h, $i);
+
+ foreach $i (@$a, @$b)
+ {
+ $h{$i} = 1;
+ }
+
+ @$a = keys %h;
+ return $a;
+}
+
+# Given an array and a pattern, it returns the index of the
+# array that contains it
+sub gst_array_find_index
+{
+ my($arrayRef, $pattern) = @_;
+ my(@array) = @{$arrayRef};
+ my($numElements) = scalar(@array);
+ my(@indexes) = (0..$numElements);
+ my(@elements);
+
+ @elements = grep @{$arrayRef}[$_] =~ /$pattern/, @indexes;
+ return(wantarray ? @elements : $elements[0]);
+}
+
+
+
+sub gst_ignore_line
+{
+ if (($_[0] =~ /^[ \t]*\#/) || ($_[0] =~ /^[ \t\n\r]*$/)) { return 1; }
+ return 0;
+}
+
+
+# &gst_item_is_in_list
+#
+# Given:
+# * A scalar value.
+# * An array.
+# this function will return 1 if the scalar value is in the array, 0 otherwise.
+
+sub gst_item_is_in_list
+{
+ my ($value, @arr) = @_;
+ my ($item);
+
+ foreach $item (@arr)
+ {
+ return 1 if $value eq $item;
+ }
+
+ return 0;
+}
+
+
+# Recursively compare a structure made of nested arrays and hashes, diving
+# into references, if necessary. Circular references will cause a loop.
+# Watch it: arrays must have elements in the same order to be equal.
+sub gst_util_struct_eq
+{
+ my ($a1, $a2) = @_;
+ my ($type1, $type2);
+ my (@keys1, @keys2);
+ my ($elem1, $elem2);
+ my $i;
+
+ $type1 = ref $a1;
+ $type2 = ref $a2;
+
+ return 0 if $type1 != $type2;
+ return 1 if $a1 eq $a2;
+ return 0 if (!$type1); # Scalars
+
+ if ($type1 eq "SCALAR") {
+ return 0 if $$a1 ne $$a2;
+ }
+ elsif ($type1 eq "ARRAY")
+ {
+ return 0 if $#$a1 != $#$a2;
+
+ for ($i = 0; $i <= $#$a1; $i++)
+ {
+ return 0 if !&gst_util_struct_eq ($$a1[$i], $$a2[$i]);
+ }
+ }
+ elsif ($type1 eq "HASH") {
+ @keys1 = sort keys (%$a1);
+ @keys2 = sort keys (%$a2);
+
+ return 0 if !&gst_util_struct_eq (\@keys1, \@keys2);
+ foreach $i (@keys1)
+ {
+ return 0 if !&gst_util_struct_eq ($$a1{$i}, $$a2{$i});
+ }
+ }
+ else
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+
+# &gst_get_key_for_subkeys
+#
+# Given:
+# * A hash-table with its values containing references to other hash-tables,
+# which are called "sub-hash-tables".
+# * A list of possible keys (stored as strings), called the "match_list".
+# this method will look through the "sub-keys" (the keys of each
+# sub-hash-table) seeing if one of them matches up with an item in the
+# match_list. If so, the key will be returned.
+
+sub gst_get_key_for_subkeys
+{
+ my %hash = %{$_[0]};
+ my @match_list = @{$_[1]};
+
+ foreach $key (keys (%hash))
+ {
+ my %subhash = %{$hash{$key}};
+ foreach $item (@match_list)
+ {
+ if ($subhash{$item} ne "") { return $key; }
+ }
+ }
+
+ return "";
+}
+
+
+# &gst_get_key_for_subkey_and_subvalues
+#
+# Given:
+# * A hash-table with its values containing references to other hash-tables,
+# which are called "sub-hash-tables". These sub-hash-tables contain
+# "sub-keys" with associated "sub-values".
+# * A sub-key, called the "match_key".
+# * A list of possible sub-values, called the "match_list".
+# this function will look through each sub-hash-table looking for an entry
+# whose:
+# * sub-key equals match_key.
+# * sub-key associated sub-value is contained in the match_list.
+
+sub gst_get_key_for_subkey_and_subvalues
+{
+ my %hash = %{$_[0]};
+ my $key;
+ my $match_key = $_[1];
+ my @match_list = @{$_[2]};
+
+ foreach $key (keys (%hash))
+ {
+ my %subhash = %{$hash{$key}};
+ my $subvalue = $subhash{$match_key};
+
+ if ($subvalue eq "") { next; }
+
+ foreach $item (@match_list)
+ {
+ if ($item eq $subvalue) { return $key; }
+ }
+ }
+
+ return "";
+}
+
+
+# --- IP calculation --- #
+
+
+# &gst_ip_calc_network (<IP>, <netmask>)
+#
+# Calculates the network address and returns it as a string.
+
+sub gst_ip_calc_network
+{
+ my @ip_reg1;
+ my @ip_reg2;
+
+ @ip_reg1 = ($_[0] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
+ @ip_reg2 = ($_[1] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
+
+ $ip_reg1[0] = ($ip_reg1[0] * 1) & ($ip_reg2[0] * 1);
+ $ip_reg1[1] = ($ip_reg1[1] * 1) & ($ip_reg2[1] * 1);
+ $ip_reg1[2] = ($ip_reg1[2] * 1) & ($ip_reg2[2] * 1);
+ $ip_reg1[3] = ($ip_reg1[3] * 1) & ($ip_reg2[3] * 1);
+
+ return join ('.', @ip_reg1);
+}
+
+
+# &gst_ip_calc_network (<IP>, <netmask>)
+#
+# Calculates the broadcast address and returns it as a string.
+
+sub gst_ip_calc_broadcast
+{
+ my @ip_reg1;
+ my @ip_reg2;
+
+ @ip_reg1 = ($_[0] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
+ @ip_reg2 = ($_[1] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
+
+ @ip_reg1 = ($cf_hostip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
+
+ $ip_reg1[0] = ($ip_reg1[0] * 1) | (~($ip_reg2[0] * 1) & 255);
+ $ip_reg1[1] = ($ip_reg1[1] * 1) | (~($ip_reg2[1] * 1) & 255);
+ $ip_reg1[2] = ($ip_reg1[2] * 1) | (~($ip_reg2[2] * 1) & 255);
+ $ip_reg1[3] = ($ip_reg1[3] * 1) | (~($ip_reg2[3] * 1) & 255);
+
+ return join ('.', @ip_reg1);
+}
+
+# Forks a process, running $proc with @args in the child, and
+# printing the returned value of $proc in the pipe. Parent
+# returns a structure with useful data about the process.
+sub gst_process_fork
+{
+ my ($proc, @args) = @_;
+ my $pid;
+ local *PARENT_RDR;
+ local *CHILD_WTR;
+
+ pipe (PARENT_RDR, CHILD_WTR);
+
+ $pid = fork ();
+ if ($pid)
+ {
+ # Parent
+ close CHILD_WTR;
+ return {"pid" => $pid, "fd" => *PARENT_RDR, "fileno" => fileno (*PARENT_RDR)};
+ }
+ else
+ {
+ my $ret;
+ close PARENT_RDR;
+ # Child
+ $ret = &$proc (@args);
+ my $type = ref ($ret);
+
+ if (!$type)
+ {
+ print CHILD_WTR $ret;
+ }
+ elsif ($type eq 'ARRAY')
+ {
+ print CHILD_WTR "$_\n" foreach (@$ret);
+ }
+
+ close CHILD_WTR;
+ exit (0);
+ }
+}
+
+
+# Close pipe, kill process, wait for it to finish.
+sub gst_process_kill
+{
+ my ($proc) = @_;
+
+ &gst_file_close ($$proc{"fd"});
+ kill 2, $$proc{"pid"};
+ waitpid ($$proc{"pid"}, undef);
+}
+
+
+# Populate a bitmap of the used file descriptors.
+sub gst_process_list_build_fd_bitmap
+{
+ my ($procs) = @_;
+ my ($bits, $proc);
+
+ foreach $proc (@$procs)
+ {
+ vec ($bits, $$proc{"fileno"}, 1) = 1;
+ }
+
+ return $bits;
+}
+
+
+# Receives a seconds timeout (may be float) and a ref to
+# a list of processes (each returned by gst_fork_process), and
+# set the "ready" key to true in all the procs that are ready
+# to return values, false otherwise. Returns time left before
+# timeout.
+sub gst_process_list_check_ready
+{
+ my ($timeout, $procs) = @_;
+ my ($bits, $bitsleft, $bitsready, $timestamp, $timeleft);
+
+ $procs = [ $procs ] if ref ($procs) ne 'ARRAY';
+ $bits = &gst_process_list_build_fd_bitmap ($procs);
+
+ # Check with timeout which descriptors are ready with info.
+ $timeout = undef if $timeout == 0;
+ $timeleft = $timeout;
+ $bitsleft = $bits;
+ while (($timeout eq undef) || ($timeleft > 0))
+ {
+ $timestamp = time;
+ select ($bitsleft, undef, undef, $timeleft);
+ $timeleft -= time - $timestamp if $timeout ne undef;
+
+ $bitsready |= $bitsleft;
+ $bitsleft = $bits & (~$bitsready);
+ last if $bitsready eq $bits;
+ }
+ $bits = $bitsready;
+
+ # For every process, set "ready" key to 1/0 depending on
+ # its file descriptor bit.
+ foreach $proc (@$procs)
+ {
+ $$proc{"ready"} = (ord ($bits) & (1 << $$proc{"fileno"}))? 1 : 0;
+ }
+
+ return $timeleft;
+}
+
+
+sub gst_process_result_collect
+{
+ my ($proc, $func, @args) = @_;
+ my ($value, $tmp, $lines);
+
+ if ($$proc{"ready"})
+ {
+ my @list;
+
+ $lines .= $tmp while (sysread ($$proc{"fd"}, $tmp, 4096));
+ goto PROC_KILL unless $lines;
+ if ($lines =~ /\n/)
+ {
+ @list = split ("\n", $lines);
+ }
+ else
+ {
+ push @list, $line;
+ }
+
+ $value = &$func (\@list, @args);
+ }
+
+ PROC_KILL:
+ &gst_process_kill ($proc);
+
+ return $value;
+}
+
+
+1;
diff --git a/knetworkconf/backends/xml.pl.in b/knetworkconf/backends/xml.pl.in
new file mode 100644
index 0000000..9ebbde5
--- /dev/null
+++ b/knetworkconf/backends/xml.pl.in
@@ -0,0 +1,1012 @@
+#!/usr/bin/env perl
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+# XML printing, scanning and parsing.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# Authors: Hans Petter Jansson <hpj@ximian.com>
+# Arturo Espinosa <arturo@ximian.com>
+# Kenneth Christiansen <kenneth@gnu.org>
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+$SCRIPTSDIR = "@scriptsdir@";
+if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
+{
+ $SCRIPTSDIR = ".";
+ $DOTIN = ".in";
+}
+
+require "$SCRIPTSDIR/util.pl$DOTIN";
+require "$SCRIPTSDIR/general.pl$DOTIN";
+require "$SCRIPTSDIR/debug.pl$DOTIN";
+
+use Text::ParseWords;
+
+$has_encode = 0;
+if (eval "require Encode") {
+ Encode->import ();
+ $has_encode = 1;
+}
+
+# --- XML print formatting --- #
+
+
+# &gst_xml_enter: Call after entering a block. Increases indent level.
+# &gst_xml_leave: Call before leaving a block. Decreases indent level.
+# &gst_xml_print_indent: Call before printing a line. Indents to current level.
+# &gst_xml_print_vspace: Ensures there is a vertical space of one and only one line.
+# &gst_xml_print: Indent, then print all arguments. Just for sugar.
+
+
+my $gst_indent_level = 0;
+my $gst_have_vspace = 0;
+
+my @gst_xml_stack;
+
+sub gst_xml_print_comment # (comment text)
+{
+ my ($comment) = @_;
+
+ &gst_xml_print_line ("<!-- $comment -->") if $comment;
+}
+
+
+sub gst_xml_print_begin
+{
+ my ($name) = @_;
+
+ $name = $gst_name if !$name;
+
+ &gst_xml_print_string ("<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n");
+ &gst_xml_print_string ("<!DOCTYPE $name []>\n\n");
+ &gst_xml_print_string ("<$name>\n");
+
+ &gst_xml_enter ();
+
+ &gst_xml_print_vspace ();
+}
+
+
+# The frontend expects exactly this string. Don not alter.
+sub gst_xml_print_request_end
+{
+ print "\n<!-- GST: end of request -->\n";
+}
+
+
+sub gst_xml_print_end
+{
+ my ($name) = @_;
+
+ $name = $gst_name if !$name;
+
+ &gst_xml_leave ();
+
+ &gst_xml_print_vspace ();
+ &gst_xml_print_string ("</$name>\n");
+}
+
+
+sub gst_xml_enter
+{
+ $gst_indent_level += 2;
+}
+
+
+sub gst_xml_leave
+{
+ $gst_indent_level -= 2;
+}
+
+
+sub gst_xml_print_string
+{
+ if ($has_encode)
+ {
+ if (&decode_utf8 ($_[0]) eq undef)
+ {
+ # we first decode the string, if it's not
+ # utf-8 (returns undef), then encode it
+ print "" . &encode_utf8 ($_[0]);
+ return;
+ }
+ }
+
+ # It could not encode the string, write it as is
+ print $_[0];
+}
+
+sub gst_xml_format_indent
+{
+ $gst_have_vspace = 0;
+ return " " x $gst_indent_level;
+}
+
+sub gst_xml_print_indent
+{
+ &gst_xml_print_string(&gst_xml_format_indent ());
+}
+
+sub gst_xml_print_vspace
+{
+ if (not $gst_have_vspace)
+ {
+ &gst_xml_print_string ("\n");
+ $gst_have_vspace = 1;
+ }
+}
+
+
+sub gst_xml_print_line
+{
+ my $line;
+ $line = join ("", @_);
+ $line =~ tr/\n//d;
+
+ &gst_xml_print_indent ();
+ &gst_xml_print_string ($line . "\n");
+}
+
+sub gst_xml_format_pcdata # (name, pcdata)
+{
+ my ($name, $pcdata) = @_;
+ return "<$name>$pcdata</$name>" if defined ($name) || defined ($pcdata);
+}
+
+sub gst_xml_print_pcdata # (name, pcdata)
+{
+ my ($name, $pcdata) = @_;
+ my $line = &gst_xml_format_pcdata ($name, $pcdata);
+
+ &gst_xml_print_line ($line) if $line;
+}
+
+sub gst_xml_format_state_tag
+{
+ my ($name, $state) = @_;
+ my $boolean = &gst_print_boolean_truefalse ($state);
+
+ return "<$name state='$boolean'/>";
+}
+
+sub gst_xml_print_state_tag
+{
+ my ($name, $state) = @_;
+ my $state_tag = &gst_xml_format_state_tag ($name, $state);
+
+ &gst_xml_print_line ($state_tag);
+}
+
+# Pass a hash and the keys whose items are scalars. Print <key>val</key>.
+sub gst_xml_print_scalars
+{
+ my ($h, @scalar_keys) = @_;
+ my ($i, $val);
+
+ @scalar_keys = sort @scalar_keys;
+
+ while ($i = shift @scalar_keys)
+ {
+ $val = &gst_xml_quote ($$h{$i});
+ &gst_xml_print_line ("<$i>$val</$i>\n") if exists $$h{$i};
+ }
+
+}
+
+# Print the @$array using <$tag>val</$tag> foreach val in the array.
+# Actually lets print_structure do that now. Just print sequentially
+# the given elements, using as $tag as the surrounding tags.
+sub gst_xml_print_array
+{
+ my ($array, $tag) = @_;
+ my ($i, $val);
+
+ return if (scalar @$array <= 0);
+
+ &gst_xml_print_vspace ();
+ foreach $i (@$array)
+ {
+ &gst_xml_print_structure ($i, $tag);
+ }
+}
+
+# Pass a hash and the keys whose items are arrays. Print <key>val</key> foreach val
+# in the array at hash{key}
+sub gst_xml_print_arrays
+{
+ my ($h, @array_keys) = @_;
+ my ($i, $j, $val);
+
+ foreach $i (sort @array_keys)
+ {
+ &gst_xml_print_array ($$h{$i}, $i) if (exists $$h{$i})
+ }
+}
+
+# Pass a hash, create a parent tag $tag and print <key>val</key> for every
+# value pair in the hash. If structure refs are found, these are recursively
+# printed with print_structure.
+sub gst_xml_print_hash
+{
+ my ($hash, $tag) = @_;
+ my ($j, $val);
+
+ &gst_xml_print_vspace ();
+ if (defined $tag) {
+ &gst_xml_print_line ("<$tag>\n");
+ &gst_xml_enter ();
+ }
+
+ foreach $j (sort keys (%$hash))
+ {
+ &gst_xml_print_structure ($$hash{$j}, $j);
+ }
+
+ if (defined $tag) {
+ &gst_xml_leave ();
+ &gst_xml_print_line ("</$tag>\n");
+ }
+}
+
+# Call the corresponding function depending on the reference
+# type of $x. If just a scalar, print <$tag>$x</$tag>.
+sub gst_xml_print_structure
+{
+ my ($x, $tag) = @_;
+
+ if (ref $x eq "ARRAY") { &gst_xml_print_array ($x, $tag); }
+ elsif (ref $x eq "HASH") { &gst_xml_print_hash ($x, $tag); }
+ else
+ {
+ &gst_xml_print_line ("<$tag>" . &gst_xml_quote ($x) . "</$tag>\n");
+ }
+}
+
+# Treats hash as an array: doesn't use the keys as tags for its
+# elements, but the given tag.
+sub gst_xml_print_hash_hash
+{
+ my ($h, $tag) = @_;
+ my $i;
+
+ foreach $i (sort keys %$h)
+ {
+ &gst_xml_print_hash ($$h{$i}, $tag);
+ }
+}
+
+
+sub gst_xml_container_enter # (name)
+{
+ my ($container) = @_;
+
+ ## gst_xml_stack is not my, as it is defined at top,
+ ## so it is global
+ push @gst_xml_stack, $container;
+
+ &gst_xml_print_line ("<$container>");
+ &gst_xml_enter();
+}
+
+
+sub gst_xml_container_leave
+{
+ ## checks if there is a start tag
+ if ($#gst_xml_stack >= 0)
+ {
+ my $current_container = pop @gst_xml_stack;
+
+ &gst_xml_leave ();
+ &gst_xml_print_line ("</$current_container>");
+ }
+}
+
+
+sub gst_xml_print_container # (name, @strings)
+{
+ my ($name, @strings) = @_;
+
+ if (@strings) {
+ &gst_xml_container_enter ($name);
+ foreach $tag (@strings) {
+ &gst_xml_print_line ("$tag");
+ }
+ &gst_xml_container_leave ();
+ }
+}
+
+# --- XML printing from in-memory model --- #
+
+sub gst_xml_model_print_attributes
+{
+ my ($tree) = @_;
+ my ($attrs, $string);
+
+ $attrs = @$tree [0];
+
+ for $attr (keys %$attrs)
+ {
+ $string .= " " . $attr . "=\"" . $$attrs{$attr} . "\"";
+ }
+
+ return $string;
+}
+
+sub gst_xml_model_print_recurse
+{
+ my ($tree, $indent) = @_;
+ my ($string);
+
+ my @children = @$tree;
+ shift @children; # Attributes
+
+ while (@children)
+ {
+ my $branch = $children [1];
+
+ if ($children [0] eq "__unparsed__")
+ {
+ $string .= "<" . $children [1] . ">";
+ }
+ elsif ($children [0] eq "0")
+ {
+ $string .= $children [1];
+ }
+ elsif (@$branch == 1) # Empty tag.
+ {
+ $string .= "<" . $children [0] . &gst_xml_model_print_attributes ($branch) . "/>";
+ }
+ else
+ {
+ $string .= "<" . $children [0] . &gst_xml_model_print_attributes ($branch) . ">";
+ $string .= &gst_xml_model_print_recurse ($branch);
+ $string .= "</" . $children [0] . ">";
+ }
+
+ shift @children;
+ shift @children;
+ }
+
+# if ($branch)
+# {
+# return &gst_xml_get_attribute ($branch, $property) if $property ne "";
+# return &gst_xml_get_pcdata ($branch);
+# }
+
+ return $string;
+}
+
+sub gst_xml_model_print
+{
+ my ($tree) = @_;
+ my ($string);
+
+ $string = &gst_xml_model_print_recurse ($tree);
+ chomp $string;
+ $string .= "\n";
+
+ return $string;
+}
+
+# --- XML scanning --- #
+
+
+# This code tries to replace XML::Parser scanning from stdin in tree mode.
+
+sub gst_xml_scan_make_kid_array
+{
+ my $line = shift;
+ my (%hash, @sublist, @attr, @list);
+
+ # Remove < and />
+ $line =~ s/^[ \t]*<//;
+ $line =~ s/[\/]?>[ \t]*$//;
+
+ my @list = &quotewords ('[ \t]+', 1, $line);
+ shift @list; # push tag name.
+
+ foreach (@list)
+ {
+ my @tmp = split '[ \t]*=[ \t]*';
+ if (scalar @tmp == 2 && $tmp[1] =~ s/[\"\']//g)
+ {
+ push @attr, @tmp;
+ }
+ }
+
+ %hash = @attr;
+
+ push (@sublist, \%hash);
+ return \@sublist;
+}
+
+
+sub gst_xml_scan_recurse
+{
+ my ($gst_xml_scan_list, $list_arg) = @_;
+ my @list;
+ if ($list_arg ne undef) { @list = $$list_arg[0]; }
+
+ while (@$gst_xml_scan_list)
+ {
+ $el = shift @$gst_xml_scan_list;
+
+ if (($el eq "") || $el =~ /^\<[!?].*\>$/s) { next; } # Empty strings, PI and DTD must go.
+ if ($el =~ /^\<.*\/\>$/s) # Empty.
+ {
+ $el =~ /^\<([a-zA-Z0-9_-]+).*\/\>$/s;
+ push (@list, $1);
+ push (@list, &gst_xml_scan_make_kid_array ($el));
+ }
+ elsif ($el =~ /^\<\/.*\>$/s) # End.
+ {
+ last;
+ }
+ elsif ($el =~ /^\<.*\>$/s) # Start.
+ {
+ $el =~ /^\<([a-zA-Z0-9_-]+).*\>$/s;
+ push (@list, $1);
+ $sublist = &gst_xml_scan_make_kid_array ($el);
+ push (@list, &gst_xml_scan_recurse ($gst_xml_scan_list, $sublist));
+ next;
+ }
+ elsif ($el ne "") # PCDATA.
+ {
+ push (@list, 0);
+ push (@list, "$el");
+ }
+ }
+
+ return \@list;
+}
+
+
+sub gst_xml_read_file
+{
+ my ($file) = @_;
+ my ($doc, $i);
+ local *INPUT_FILE;
+
+ open INPUT_FILE, $file;
+ $doc .= $i while ($i = <INPUT_FILE>);
+ close INPUT_FILE;
+
+ return $doc;
+}
+
+
+sub gst_xml_read_compressed_file
+{
+ my ($file) = @_;
+ my ($doc, $i, $fd);
+
+ $fd = &gst_file_run_pipe_read ("gunzip -c $file");
+ return undef if $fd eq undef;
+ $doc .= $i while ($i = <$fd>);
+ &gst_file_close ($fd);
+
+ if (length ($doc) < 4) # Allow for one blank line from gzip, '\n\r'.
+ {
+ $doc = undef;
+ }
+
+ return $doc;
+}
+
+
+sub gst_xml_read_stdin
+{
+ my ($i, $doc);
+
+ do {
+ $i = <STDIN>;
+
+ if ($i ne undef)
+ {
+ $doc .=$i;
+ }
+ } while (! ($i =~ /^<!-- GST: end of request -->$/));
+
+ return $doc;
+}
+
+# (file, tool) If no file specified, reads stdin.
+# file could also contain xml document.
+# If tool is an gst_tool, stores the read buffer in
+# $$tool{"xml_doc"}.
+sub gst_xml_scan
+{
+ my ($file, $tool) = @_;
+ my ($doc, @tree, @gst_xml_scan_list);
+
+ $file = $gst_input_file unless $file;
+
+ if ($file && stat ($file))
+ {
+ $doc = &gst_xml_read_file ($file);
+ }
+ elsif ($file)
+ {
+ $doc = $file;
+ }
+ else
+ {
+ $doc = &gst_xml_read_stdin ();
+ }
+
+ # remove any blank or carriage return at the beginning of the xml
+ $doc =~ s/^[ \n]*//;
+
+ &gst_debug_print_log_to_file ("in.xml", $doc);
+
+ $$tool{"xml_doc"} = $doc if (&gst_is_tool ($tool));
+
+ @gst_xml_scan_list = ($doc =~ /([^\<]*)(\<[^\>]*\>)[ \t\n\r]*/mg); # pcdata, tag, pcdata, tag, ...
+ $tree = &gst_xml_scan_recurse (\@gst_xml_scan_list);
+
+ return $tree;
+}
+
+# XML scanning that preserves more exact attributes of the scanned XML.
+
+sub gst_xml_model_scan_recurse
+{
+ my @list;
+ if (@_) { @list = $_[0]->[0]; }
+
+ while (@gst_xml_scan_list)
+ {
+ $el = $gst_xml_scan_list[0]; shift @gst_xml_scan_list;
+
+ if ($el eq "") # Empty strings.
+ {
+ next;
+ }
+ elsif ($el =~ /^\<[!?].*\>$/s) # PI and DTD.
+ {
+ $el =~ /^\<([^\>]+)\>$/s;
+ push (@list, "__unparsed__");
+ push (@list, $1);
+ }
+ elsif ($el =~ /^\<.*\/\>$/s) # Empty.
+ {
+ $el =~ /^\<([a-zA-Z0-9_-]+).*\/\>$/s;
+ push (@list, $1);
+ push (@list, &gst_xml_scan_make_kid_array ($el));
+ }
+ elsif ($el =~ /^\<\/.*\>$/s) # End.
+ {
+ last;
+ }
+ elsif ($el =~ /^\<.*\>$/s) # Start.
+ {
+ $el =~ /^\<([a-zA-Z0-9_-]+).*\>$/s;
+ push (@list, $1);
+ $sublist = &gst_xml_scan_make_kid_array ($el);
+ push (@list, &gst_xml_model_scan_recurse ($sublist));
+ next;
+ }
+ elsif ($el ne "") # PCDATA.
+ {
+ push (@list, 0);
+ push (@list, "$el");
+ }
+ }
+
+ return \@list;
+}
+
+sub gst_xml_model_scan # (file) If no file specified, reads stdin.
+{
+ my ($file) = @_;
+ my ($doc, $tree, $compressed);
+
+ $file = $gst_input_file if $file eq undef;
+
+ if ($file)
+ {
+ $doc = &gst_xml_read_compressed_file ($file);
+ if (!$doc)
+ {
+ $doc = &gst_xml_read_file ($file);
+ $compressed = 0;
+ }
+ else
+ {
+ $compressed = 1;
+ }
+ }
+ else
+ {
+ return undef, 0;
+ }
+
+ @gst_xml_scan_list = ($doc =~ /([^\<]*)(\<[^\>]*\>)/mg); # pcdata, tag, pcdata, tag, ...
+ $tree = &gst_xml_model_scan_recurse;
+
+ return $tree, $compressed;
+}
+
+sub gst_xml_model_save
+{
+ my ($model, $file, $compressed) = @_;
+ my $fd;
+
+ if ($compressed == 1)
+ {
+ $fd = &gst_file_open_write_compressed ($file);
+ }
+ else
+ {
+ $fd = &gst_file_open_write_from_names ($file);
+ }
+
+ if ($fd == -1) { return -1; }
+
+ print $fd &gst_xml_model_print ($model);
+ &gst_file_close ($fd);
+
+ return 0;
+}
+
+# Quote/unquote.
+
+@gst_xml_entities = ( "&lt;", '<', "&gt;", '>', "&apos;", '\'', "&quot;", '"', "&amp;", '&' );
+
+
+sub gst_xml_quote
+{
+ my $in = $_[0];
+ my $out = "";
+ my @xe;
+ my $joined = 0;
+
+ my @clist = split (//, $in);
+
+ while (@clist)
+ {
+ # Find character and join its entity equivalent.
+ # If none found, simply join the character.
+
+ $joined = 0; # Cumbersome.
+
+ for (@xe = @gst_xml_entities; @xe && !$joined; )
+ {
+ if ($xe [1] eq $clist [0]) { $out = join ('', $out, $xe [0]); $joined = 1; }
+ shift @xe; shift @xe;
+ }
+
+ if (!$joined) { $out = join ('', $out, $clist [0]); }
+ shift @clist;
+ }
+
+ return $out;
+}
+
+
+sub gst_xml_unquote
+{
+ my $ret = $_[0];
+ my $i;
+
+ #print STDERR "INI U: $ret\n";
+
+ for ($i = 0; $gst_xml_entities[$i] ne undef; $i += 2)
+ {
+ $ret =~ s/$gst_xml_entities[$i]/$gst_xml_entities[$i + 1]/g;
+ }
+
+ while ($ret =~ /&#([0-9]+);/)
+ {
+ $num = $1;
+ $c = chr ($num);
+ $ret =~ s/&#$num;/$c/g;
+ }
+
+ #print STDERR "END U: $ret\n";
+
+ return $ret;
+}
+
+
+# --- XML parsing --- #
+
+
+sub gst_xml_get_pcdata
+{
+ my $tree = $_[0];
+ my $retval;
+
+ shift @$tree; # Skip attributes.
+
+ while (@$tree)
+ {
+ if ($$tree[0] == 0)
+ {
+ $retval = &gst_xml_unquote ($$tree[1]);
+ &gst_debug_print_line ("gst_xml_get_pcdata: $retval");
+ return ($retval);
+ }
+
+ shift @$tree;
+ shift @$tree;
+ }
+
+ return "";
+}
+
+# Compresses node into a word and returns it.
+
+sub gst_xml_get_word
+{
+ my $tree = $_[0];
+ my $retval;
+
+ $retval = &gst_xml_get_pcdata ($tree);
+ $retval =~ tr/ \n\r\t\f//d;
+ return $retval;
+}
+
+
+# Compresses node into a size and returns it.
+
+sub gst_xml_get_size
+{
+ my $tree = $_[0];
+ my $retval;
+
+ $retval = &gst_xml_get_word ($tree);
+ if ($retval =~ /Mb$/)
+ {
+ $retval =~ tr/ Mb//d;
+ $retval *= 1024;
+ }
+
+ return $retval;
+}
+
+
+# Replaces misc. whitespace with spaces and returns text.
+
+sub gst_xml_get_text
+{
+ my $tree = $_[0];
+ my $retval;
+
+ $retval = &gst_xml_get_pcdata ($tree);
+ my $type = ref ($retval);
+
+ if (!$type) { $retval =~ tr/\n\r\t\f/ /; }
+
+ return $retval;
+}
+
+sub gst_xml_get_attribute
+{
+ my ($tree, $attr) = @_;
+
+ return $$tree[0]->{$attr};
+}
+
+sub gst_xml_get_state
+{
+ my ($tree) = @_;
+
+ # Check attribute; 'yes', 'true', 'no', 'false'.
+ return &gst_util_read_boolean ($$tree[0]->{state});
+}
+
+# XML model operations.
+
+# Locate a node from the branch leading up to it.
+sub gst_xml_model_find
+{
+ my ($model, $varpath) = @_;
+ my ($branch, @path);
+
+ $branch = $model;
+ @path = split /\//, $varpath;
+
+ for $elem (@path)
+ {
+ next if ($elem eq "");
+ my @children = @$branch;
+ shift @children; # Attributes
+ $branch = undef;
+
+ while (@children)
+ {
+ if ($children [0] eq $elem)
+ {
+ shift @children;
+ $branch = shift @children;
+ last;
+ }
+
+ shift @children;
+ shift @children;
+ }
+
+ last if ($branch == undef);
+ }
+
+ return $branch;
+}
+
+# Add a branch to another branch. Allows duplicates.
+sub gst_xml_model_add
+{
+ my ($model, $varpath, $addpath) = @_;
+ my ($branch, @path);
+
+ @path = split /\//, $addpath;
+ $branch = &gst_xml_model_find ($model, $varpath);
+ if ($branch == undef)
+ {
+ return -1;
+ }
+
+ for $elem (@path)
+ {
+ my %hash;
+ my @list = ();
+
+ push @list, \%hash;
+
+ push @$branch, $elem;
+ push @$branch, \@list;
+
+ $branch = \@list;
+ }
+
+ return 0;
+}
+
+# Ensure a branch exists, by extending the branch with given elements, if needed.
+sub gst_xml_model_ensure
+{
+ my ($model, $varpath) = @_;
+ my ($branch, @path);
+
+ $branch = $model;
+ @path = split /\//, $varpath;
+
+ for $elem (@path)
+ {
+ next if ($elem eq "");
+
+ my @children = @$branch;
+ my $parent_branch = $branch;
+
+ shift @children; # Attributes
+ $branch = undef;
+
+ while (@children)
+ {
+ if ($children [0] eq $elem)
+ {
+ shift @children;
+ $branch = shift @children;
+ last;
+ }
+
+ shift @children;
+ shift @children;
+ }
+
+ if ($branch == undef)
+ {
+ my %hash;
+ my @list = ();
+
+ $branch = \@list;
+
+ push @list, \%hash;
+
+ push @$parent_branch, $elem;
+ push @$parent_branch, $branch;
+ }
+ }
+
+ return $branch;
+}
+
+sub gst_xml_model_remove
+{
+ my ($model, $varpath, $tag) = @_;
+ my ($branch, $i);
+
+ @path = split /\//, $addpath;
+ $branch = &gst_xml_model_find ($model, $varpath);
+ if ($branch == undef)
+ {
+ return -1;
+ }
+
+ for ($i = 1; $i < @$branch; $i += 2)
+ {
+ if (@$branch [$i] eq $tag)
+ {
+ @$branch = (@$branch [0 .. $i - 1], @$branch [$i + 2 .. @$branch - 1]);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+sub gst_xml_model_get_children
+{
+ my ($branch) = @_;
+ my (@children);
+
+ if (!$branch) { return \@children; }
+
+ for ($i = 1; $i < @$branch; $i += 2)
+ {
+ if (@$branch [$i] ne "__unparsed__" && @$branch [$i] ne "0")
+ {
+ push @children, @$branch [$i + 1];
+ }
+ }
+
+ return \@children;
+}
+
+sub gst_xml_model_get_pcdata
+{
+ my ($branch) = @_;
+ my ($i);
+
+ for ($i = 1; $i < @$branch; $i += 2)
+ {
+ if ($$branch [$i] == 0)
+ {
+ my $retval = &gst_xml_unquote ($$branch [$i + 1]);
+ return ($retval);
+ }
+ }
+
+ return "";
+}
+
+sub gst_xml_model_set_pcdata
+{
+ my ($branch, $pcdata) = @_;
+
+ @$branch = (@$branch [0]);
+
+ $$branch [1] = 0;
+ $$branch [2] = &gst_xml_quote ($pcdata);
+}
+
+sub gst_xml_model_get_attribute
+{
+ my ($branch, $attr) = @_;
+
+ return $$branch[0]->{$attr};
+}
+
+sub gst_xml_model_set_attribute
+{
+ my ($branch, $attr, $value) = @_;
+
+ return $$branch[0]->{$attr} = $value;
+}
+
+1;