summaryrefslogtreecommitdiffstats
path: root/dselect/methods
diff options
context:
space:
mode:
Diffstat (limited to 'dselect/methods')
-rw-r--r--dselect/methods/Dselect/Ftp.pm410
-rw-r--r--dselect/methods/Makefile.am56
-rw-r--r--dselect/methods/Makefile.in755
-rw-r--r--dselect/methods/file/desc.file8
-rwxr-xr-xdselect/methods/file/install.sh124
-rw-r--r--dselect/methods/file/names1
-rwxr-xr-xdselect/methods/file/setup.sh305
-rwxr-xr-xdselect/methods/file/update.sh84
-rw-r--r--dselect/methods/ftp/desc.ftp2
-rwxr-xr-xdselect/methods/ftp/install.pl624
-rw-r--r--dselect/methods/ftp/names1
-rwxr-xr-xdselect/methods/ftp/setup.pl177
-rwxr-xr-xdselect/methods/ftp/update.pl250
-rw-r--r--dselect/methods/media/README.media101
-rw-r--r--dselect/methods/media/desc.media3
-rwxr-xr-xdselect/methods/media/install.sh285
-rw-r--r--dselect/methods/media/names1
-rwxr-xr-xdselect/methods/media/setup.sh485
-rwxr-xr-xdselect/methods/media/update.sh125
19 files changed, 3797 insertions, 0 deletions
diff --git a/dselect/methods/Dselect/Ftp.pm b/dselect/methods/Dselect/Ftp.pm
new file mode 100644
index 0000000..154b511
--- /dev/null
+++ b/dselect/methods/Dselect/Ftp.pm
@@ -0,0 +1,410 @@
+# 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; version 2 of the License.
+#
+# 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, see <https://www.gnu.org/licenses/>.
+
+package Dselect::Ftp;
+
+use strict;
+use warnings;
+
+our $VERSION = '0.02';
+our @EXPORT = qw(
+ %CONFIG
+ yesno
+ nb
+ do_connect
+ do_mdtm
+ view_mirrors
+ add_site
+ edit_site
+ edit_config
+ read_config
+ store_config
+);
+
+use Exporter qw(import);
+use Carp;
+
+eval q{
+ use Net::FTP;
+ use Data::Dumper;
+
+ use Dpkg::File;
+};
+if ($@) {
+ warn "Missing Dpkg modules required by the FTP access method.\n\n";
+ exit 1;
+}
+
+our %CONFIG;
+
+sub nb {
+ my $nb = shift;
+ if ($nb > 1024**2) {
+ return sprintf('%.2fM', $nb / 1024**2);
+ } elsif ($nb > 1024) {
+ return sprintf('%.2fk', $nb / 1024);
+ } else {
+ return sprintf('%.2fb', $nb);
+ }
+}
+
+sub read_config {
+ my $vars = shift;
+ my ($code, $conf);
+
+ eval {
+ $code = file_slurp($vars);
+ };
+ if ($@) {
+ warn "$@\n";
+ die "Try to relaunch the 'Access' step in dselect, thanks.\n";
+ }
+
+ my $VAR1; ## no critic (Variables::ProhibitUnusedVariables)
+ $conf = eval $code;
+ die "couldn't eval $vars content: $@\n" if ($@);
+ if (ref($conf) =~ /HASH/) {
+ foreach (keys %{$conf}) {
+ $CONFIG{$_} = $conf->{$_};
+ }
+ } else {
+ print "Bad $vars file : removing it.\n";
+ print "Please relaunch the 'Access' step in dselect. Thanks.\n";
+ unlink $vars;
+ exit 0;
+ }
+}
+
+sub store_config {
+ my $vars = shift;
+
+ # Check that config is completed
+ return if not $CONFIG{done};
+
+ file_dump($vars, Dumper(\%CONFIG));
+}
+
+sub view_mirrors {
+ print <<'MIRRORS';
+Please see <https://www.debian.org/mirror/list> for a current
+list of Debian mirror sites.
+MIRRORS
+}
+
+sub edit_config {
+ my $methdir = shift;
+ my $i;
+
+ #Get a config for ftp sites
+ while(1) {
+ $i = 1;
+ print "\n\nList of selected ftp sites :\n";
+ foreach (@{$CONFIG{site}}) {
+ print "$i. ftp://$_->[0]$_->[1] @{$_->[2]}\n";
+ $i++;
+ }
+ print "\nEnter a command (a=add e=edit d=delete q=quit m=mirror list) \n";
+ print 'eventually followed by a site number : ';
+ chomp($_ = <STDIN>);
+ /q/i && last;
+ /a/i && add_site();
+ /d\s*(\d+)/i &&
+ do {
+ splice(@{$CONFIG{site}}, $1 - 1, 1) if ($1 <= @{$CONFIG{site}});
+ next;};
+ /e\s*(\d+)/i &&
+ do {
+ edit_site($CONFIG{site}[$1 - 1]) if ($1 <= @{$CONFIG{site}});
+ next; };
+ /m/i && view_mirrors();
+ }
+
+ print "\n";
+ $CONFIG{use_auth_proxy} = yesno($CONFIG{use_auth_proxy} ? 'y' : 'n',
+ 'Go through an authenticated proxy');
+
+ if ($CONFIG{use_auth_proxy}) {
+ print "\nEnter proxy hostname [$CONFIG{proxyhost}] : ";
+ chomp($_ = <STDIN>);
+ $CONFIG{proxyhost} = $_ || $CONFIG{proxyhost};
+
+ print "\nEnter proxy log name [$CONFIG{proxylogname}] : ";
+ chomp($_ = <STDIN>);
+ $CONFIG{proxylogname} = $_ || $CONFIG{proxylogname};
+
+ print "\nEnter proxy password [$CONFIG{proxypassword}] : ";
+ chomp ($_ = <STDIN>);
+ $CONFIG{proxypassword} = $_ || $CONFIG{proxypassword};
+ }
+
+ print "\nEnter directory to download binary package files to\n";
+ print "(relative to $methdir)\n";
+ while(1) {
+ print "[$CONFIG{dldir}] : ";
+ chomp($_ = <STDIN>);
+ s{/$}{};
+ $CONFIG{dldir} = $_ if ($_);
+ last if -d "$methdir/$CONFIG{dldir}";
+ print "$methdir/$CONFIG{dldir} is not a directory !\n";
+ }
+}
+
+sub add_site {
+ my $pas = 1;
+ my $user = 'anonymous';
+ my $email = qx(whoami);
+ chomp $email;
+ $email .= '@' . qx(cat /etc/mailname || dnsdomainname);
+ chomp $email;
+ my $dir = '/debian';
+
+ push (@{$CONFIG{site}}, [ '', $dir, [ 'dists/stable/main',
+ 'dists/stable/contrib',
+ 'dists/stable/non-free' ],
+ $pas, $user, $email ]);
+ edit_site($CONFIG{site}[@{$CONFIG{site}} - 1]);
+}
+
+sub edit_site {
+ my $site = shift;
+
+ local($_);
+
+ print "\nEnter ftp site [$site->[0]] : ";
+ chomp($_ = <STDIN>);
+ $site->[0] = $_ || $site->[0];
+
+ print "\nUse passive mode [" . ($site->[3] ? 'y' : 'n') . '] : ';
+ chomp($_ = <STDIN>);
+ $site->[3] = (/y/i ? 1 : 0) if ($_);
+
+ print "\nEnter username [$site->[4]] : ";
+ chomp($_ = <STDIN>);
+ $site->[4] = $_ || $site->[4];
+
+ print <<'EOF';
+
+If you're using anonymous ftp to retrieve files, enter your email
+address for use as a password. Otherwise enter your password,
+or "?" if you want dselect-ftp to prompt you each time.
+
+EOF
+
+ print "Enter password [$site->[5]] : ";
+ chomp($_ = <STDIN>);
+ $site->[5] = $_ || $site->[5];
+
+ print "\nEnter debian directory [$site->[1]] : ";
+ chomp($_ = <STDIN>);
+ $site->[1] = $_ || $site->[1];
+
+ print "\nEnter space separated list of distributions to get\n";
+ print "[@{$site->[2]}] : ";
+ chomp($_ = <STDIN>);
+ $site->[2] = [ split(/\s+/) ] if $_;
+}
+
+sub yesno($$) {
+ my ($d, $msg) = @_;
+
+ my ($res, $r);
+ $r = -1;
+ $r = 0 if $d eq 'n';
+ $r = 1 if $d eq 'y';
+ croak 'incorrect usage of yesno, stopped' if $r == -1;
+ while (1) {
+ print $msg, " [$d]: ";
+ $res = <STDIN>;
+ $res =~ /^[Yy]/ and return 1;
+ $res =~ /^[Nn]/ and return 0;
+ $res =~ /^[ \t]*$/ and return $r;
+ print "Please enter one of the letters 'y' or 'n'\n";
+ }
+}
+
+##############################
+
+sub do_connect {
+ my (%opts) = @_;
+
+ my($rpass,$remotehost,$remoteuser,$ftp);
+
+ TRY_CONNECT:
+ while(1) {
+ my $exit = 0;
+
+ if ($opts{useproxy}) {
+ $remotehost = $opts{proxyhost};
+ $remoteuser = $opts{username} . '@' . $opts{ftpsite};
+ } else {
+ $remotehost = $opts{ftpsite};
+ $remoteuser = $opts{username};
+ }
+ print "Connecting to $opts{ftpsite}...\n";
+ $ftp = Net::FTP->new($remotehost, Passive => $opts{passive});
+ if(!$ftp || !$ftp->ok) {
+ print "Failed to connect\n";
+ $exit = 1;
+ }
+ if (!$exit) {
+# $ftp->debug(1);
+ if ($opts{useproxy}) {
+ print "Login on $opts{proxyhost}...\n";
+ $ftp->_USER($opts{proxylogname});
+ $ftp->_PASS($opts{proxypassword});
+ }
+ print "Login as $opts{username}...\n";
+ if ($opts{password} eq '?') {
+ print 'Enter password for ftp: ';
+ system('stty', '-echo');
+ $rpass = <STDIN>;
+ chomp $rpass;
+ print "\n";
+ system('stty', 'echo');
+ } else {
+ $rpass = $opts{password};
+ }
+ if(!$ftp->login($remoteuser, $rpass))
+ { print $ftp->message() . "\n"; $exit = 1; }
+ }
+ if (!$exit) {
+ print "Setting transfer mode to binary...\n";
+ if(!$ftp->binary()) { print $ftp->message . "\n"; $exit = 1; }
+ }
+ if (!$exit) {
+ print "Cd to '$opts{ftpdir}'...\n";
+ if (!$ftp->cwd($opts{ftpdir})) {
+ print $ftp->message . "\n";
+ $exit = 1;
+ }
+ }
+
+ if ($exit) {
+ if (yesno ('y', 'Retry connection at once')) {
+ next TRY_CONNECT;
+ } else {
+ die 'error';
+ }
+ }
+
+ last TRY_CONNECT;
+ }
+
+# if(!$ftp->pasv()) { print $ftp->message . "\n"; die 'error'; }
+
+ return $ftp;
+}
+
+##############################
+
+# assume server supports MDTM - will be adjusted if needed
+my $has_mdtm = 1;
+
+my %months = (
+ Jan => 0,
+ Feb => 1,
+ Mar => 2,
+ Apr => 3,
+ May => 4,
+ Jun => 5,
+ Jul => 6,
+ Aug => 7,
+ Sep => 8,
+ Oct => 9,
+ Nov => 10,
+ Dec => 11,
+);
+
+my $ls_l_re = qr<
+ ([^ ]+\ *){5} # Perms, Links, User, Group, Size
+ [^ ]+ # Blanks
+ \ ([A-Z][a-z]{2}) # Month name (abbreviated)
+ \ ([0-9 ][0-9]) # Day of month
+ \ ([0-9 ][0-9][:0-9][0-9]{2}) # Filename
+>x;
+
+sub do_mdtm {
+ my ($ftp, $file) = @_;
+ my ($time);
+
+ #if ($has_mdtm) {
+ $time = $ftp->mdtm($file);
+# my $code = $ftp->code();
+# my $message = $ftp->message();
+# print " [ $code: $message ] ";
+ if ($ftp->code() == 502 || # MDTM not implemented
+ $ftp->code() == 500) { # command not understood (SUN firewall)
+ $has_mdtm = 0;
+ } elsif (!$ftp->ok()) {
+ return;
+ }
+ #}
+
+ if (! $has_mdtm) {
+ require Time::Local;
+
+ my @files = $ftp->dir($file);
+ if (($#files == -1) ||
+ ($ftp->code == 550)) { # No such file or directory
+ return;
+ }
+
+# my $code = $ftp->code();
+# my $message = $ftp->message();
+# print " [ $code: $message ] ";
+
+# print "[$#files]";
+
+ # get the date components from the output of 'ls -l'
+ if ($files[0] =~ $ls_l_re) {
+ my($month_name, $day, $year_or_time, $month, $hours, $minutes,
+ $year);
+
+ # what we can read
+ $month_name = $2;
+ $day = 0 + $3;
+ $year_or_time = $4;
+
+ # translate the month name into number
+ $month = $months{$month_name};
+
+ # recognize time or year, and compute missing one
+ if ($year_or_time =~ /([0-9]{2}):([0-9]{2})/) {
+ $hours = 0 + $1; $minutes = 0 + $2;
+ my @this_date = gmtime(time());
+ my $this_month = $this_date[4];
+ my $this_year = $this_date[5];
+ if ($month > $this_month) {
+ $year = $this_year - 1;
+ } else {
+ $year = $this_year;
+ }
+ } elsif ($year_or_time =~ / [0-9]{4}/) {
+ $hours = 0; $minutes = 0;
+ $year = $year_or_time - 1900;
+ } else {
+ die 'cannot parse year-or-time';
+ }
+
+ # build a system time
+ $time = Time::Local::timegm(0, $minutes, $hours, $day, $month, $year);
+ } else {
+ die 'regex match failed on LIST output';
+ }
+ }
+
+ return $time;
+}
+
+1;
+
+__END__
diff --git a/dselect/methods/Makefile.am b/dselect/methods/Makefile.am
new file mode 100644
index 0000000..d8404b5
--- /dev/null
+++ b/dselect/methods/Makefile.am
@@ -0,0 +1,56 @@
+## Process this file with automake to produce Makefile.in
+
+methodsdir = $(pkglibexecdir)/methods
+
+nobase_dist_methods_DATA = \
+ file/names \
+ file/desc.file \
+ ftp/names \
+ ftp/desc.ftp \
+ media/names \
+ media/desc.media \
+ # EOL
+
+nobase_methods_SCRIPTS = \
+ file/install \
+ file/setup \
+ file/update \
+ ftp/install \
+ ftp/setup \
+ ftp/update \
+ media/install \
+ media/setup \
+ media/update \
+ # EOL
+
+perllibdir = $(PERL_LIBDIR)
+nobase_dist_perllib_DATA = \
+ Dselect/Ftp.pm \
+ # EOL
+
+EXTRA_DIST = \
+ file/setup.sh \
+ file/update.sh \
+ file/install.sh \
+ ftp/setup.pl \
+ ftp/update.pl \
+ ftp/install.pl \
+ media/setup.sh \
+ media/update.sh \
+ media/install.sh \
+ media/README.media \
+ # EOL
+
+CLEANFILES = \
+ $(nobase_methods_SCRIPTS) \
+ # EOL
+
+SUFFIXES =
+
+include $(top_srcdir)/build-aux/subst.am
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/mnt
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/file
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/ftp
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/media
diff --git a/dselect/methods/Makefile.in b/dselect/methods/Makefile.in
new file mode 100644
index 0000000..3516449
--- /dev/null
+++ b/dselect/methods/Makefile.in
@@ -0,0 +1,755 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Build time variable substitution for generated files.
+#
+
+# Shell support.
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = dselect/methods
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/dpkg-arch.m4 \
+ $(top_srcdir)/m4/dpkg-build.m4 \
+ $(top_srcdir)/m4/dpkg-compiler.m4 \
+ $(top_srcdir)/m4/dpkg-coverage.m4 \
+ $(top_srcdir)/m4/dpkg-funcs.m4 $(top_srcdir)/m4/dpkg-libs.m4 \
+ $(top_srcdir)/m4/dpkg-linker.m4 $(top_srcdir)/m4/dpkg-progs.m4 \
+ $(top_srcdir)/m4/dpkg-types.m4 \
+ $(top_srcdir)/m4/dpkg-unicode.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/host-cpu-c-abi.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(nobase_dist_methods_DATA) \
+ $(nobase_dist_perllib_DATA) $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(methodsdir)" "$(DESTDIR)$(methodsdir)" \
+ "$(DESTDIR)$(perllibdir)"
+SCRIPTS = $(nobase_methods_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DATA = $(nobase_dist_methods_DATA) $(nobase_dist_perllib_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/subst.am
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOM4TE = @AUTOM4TE@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_DEVEL_DOCS = @BUILD_DEVEL_DOCS@
+BZ2_LIBS = @BZ2_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CURSES_LIBS = @CURSES_LIBS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+GCOV = @GCOV@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KVM_LIBS = @KVM_LIBS@
+LCOV = @LCOV@
+LCOV_GENHTML = @LCOV_GENHTML@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+LZMA_LIBS = @LZMA_LIBS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MD_LIBS = @MD_LIBS@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_BUG_WEB = @PACKAGE_BUG_WEB@
+PACKAGE_COPYRIGHT_HOLDER = @PACKAGE_COPYRIGHT_HOLDER@
+PACKAGE_CPAN_NAME = @PACKAGE_CPAN_NAME@
+PACKAGE_DIST_IS_RELEASE = @PACKAGE_DIST_IS_RELEASE@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_RELEASE_DATE = @PACKAGE_RELEASE_DATE@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VCS_TYPE = @PACKAGE_VCS_TYPE@
+PACKAGE_VCS_URL = @PACKAGE_VCS_URL@
+PACKAGE_VCS_WEB = @PACKAGE_VCS_WEB@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATCH = @PATCH@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_COVER = @PERL_COVER@
+PERL_COVERAGE = @PERL_COVERAGE@
+PERL_LIBDIR = @PERL_LIBDIR@
+PERL_MIN_VERSION = @PERL_MIN_VERSION@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PO4A = @PO4A@
+POD2MAN = @POD2MAN@
+POSUB = @POSUB@
+PS_LIBS = @PS_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKET_LIBS = @SOCKET_LIBS@
+STRIP = @STRIP@
+TAR = @TAR@
+USE_NLS = @USE_NLS@
+USE_PO4A = @USE_PO4A@
+USE_UNICODE = @USE_UNICODE@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+ZSTD_LIBS = @ZSTD_LIBS@
+Z_LIBS = @Z_LIBS@
+Z_NG_LIBS = @Z_NG_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+admindir = @admindir@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+backupsdir = @backupsdir@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+devlibdir = @devlibdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+logdir = @logdir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfdir = @pkgconfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+zshcompletionsdir = @zshcompletionsdir@
+methodsdir = $(pkglibexecdir)/methods
+nobase_dist_methods_DATA = \
+ file/names \
+ file/desc.file \
+ ftp/names \
+ ftp/desc.ftp \
+ media/names \
+ media/desc.media \
+ # EOL
+
+nobase_methods_SCRIPTS = \
+ file/install \
+ file/setup \
+ file/update \
+ ftp/install \
+ ftp/setup \
+ ftp/update \
+ media/install \
+ media/setup \
+ media/update \
+ # EOL
+
+perllibdir = $(PERL_LIBDIR)
+nobase_dist_perllib_DATA = \
+ Dselect/Ftp.pm \
+ # EOL
+
+EXTRA_DIST = \
+ file/setup.sh \
+ file/update.sh \
+ file/install.sh \
+ ftp/setup.pl \
+ ftp/update.pl \
+ ftp/install.pl \
+ media/setup.sh \
+ media/update.sh \
+ media/install.sh \
+ media/README.media \
+ # EOL
+
+CLEANFILES = \
+ $(nobase_methods_SCRIPTS) \
+ # EOL
+
+SUFFIXES = .sh .pl
+do_shell_subst = $(AM_V_GEN) $(SED) \
+ -e "s:^ADMINDIR=.*$$:ADMINDIR='$(admindir)':" \
+ -e "s:^BACKUPSDIR=.*$$:BACKUPSDIR='$(backupsdir)':" \
+ -e "s:^PKGDATADIR_DEFAULT=.*$$:PKGDATADIR_DEFAULT='$(pkgdatadir)':" \
+ -e "s:^version=['\"][^'\"]*[\"']:version=\"$(PACKAGE_VERSION)\":" \
+ # EOL
+
+
+# Perl support.
+do_perl_subst = $(AM_V_GEN) $(SED) \
+ -e "s:^\#![[:space:]]*/usr/bin/perl:\#!$(PERL):" \
+ -e "s:our \$$CONFDIR = .*;:our \$$CONFDIR = '$(pkgconfdir)';:" \
+ -e "s:our \$$ADMINDIR = .*;:our \$$ADMINDIR = '$(admindir)';:" \
+ -e "s:our \$$LIBDIR = .*;:our \$$LIBDIR = '$(pkglibexecdir)';:" \
+ -e "s:our \$$DATADIR = .*;:our \$$DATADIR = '$(pkgdatadir)';:" \
+ -e "s:our \$$PROGMAKE = .*;:our \$$PROGMAKE = '$(MAKE)';:" \
+ -e "s:our \$$PROGTAR = .*;:our \$$PROGTAR = '$(TAR)';:" \
+ -e "s:our \$$PROGPATCH = .*;:our \$$PROGPATCH = '$(PATCH)';:" \
+ -e "s:our \$$PROGVERSION = .*;:our \$$PROGVERSION = '$(PACKAGE_VERSION)';:" \
+ # EOL
+
+
+# Makefile support.
+do_make_subst = $(AM_V_GEN) $(SED) \
+ -e "s:dpkg_datadir[[:space:]]*=[[:space:]]*[^[:space:]]*:dpkg_datadir = $(pkgdatadir):" \
+ # EOL
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .sh .pl
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build-aux/subst.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign dselect/methods/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign dselect/methods/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/build-aux/subst.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-nobase_methodsSCRIPTS: $(nobase_methods_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ @list='$(nobase_methods_SCRIPTS)'; test -n "$(methodsdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(methodsdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(methodsdir)" || exit 1; \
+ fi; \
+ $(am__nobase_strip_setup); \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e "s|$$srcdirstrip/||" -e 'h;s|[^/]*$$||; s|^$$|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$4, $$1 } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ case $$type in \
+ d) echo " $(MKDIR_P) '$(DESTDIR)$(methodsdir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(methodsdir)/$$dir" || exit $$?;; \
+ f) \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(methodsdir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(methodsdir)$$dir" || exit $$?; \
+ } \
+ ;; esac \
+ ; done
+
+uninstall-nobase_methodsSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_methods_SCRIPTS)'; test -n "$(methodsdir)" || exit 0; \
+ $(am__nobase_strip_setup); \
+ files=`$(am__nobase_strip) \
+ -e 'h;s,.*/,,;$(transform);x;s|[^/]*$$||;G;s,\n,,'`; \
+ dir='$(DESTDIR)$(methodsdir)'; $(am__uninstall_files_from_dir)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-nobase_dist_methodsDATA: $(nobase_dist_methods_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(nobase_dist_methods_DATA)'; test -n "$(methodsdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(methodsdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(methodsdir)" || exit 1; \
+ fi; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(methodsdir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(methodsdir)/$$dir"; }; \
+ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(methodsdir)/$$dir'"; \
+ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(methodsdir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_dist_methodsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_dist_methods_DATA)'; test -n "$(methodsdir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ dir='$(DESTDIR)$(methodsdir)'; $(am__uninstall_files_from_dir)
+install-nobase_dist_perllibDATA: $(nobase_dist_perllib_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(nobase_dist_perllib_DATA)'; test -n "$(perllibdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(perllibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(perllibdir)" || exit 1; \
+ fi; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(perllibdir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(perllibdir)/$$dir"; }; \
+ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(perllibdir)/$$dir'"; \
+ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(perllibdir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_dist_perllibDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_dist_perllib_DATA)'; test -n "$(perllibdir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ dir='$(DESTDIR)$(perllibdir)'; $(am__uninstall_files_from_dir)
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(SCRIPTS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(methodsdir)" "$(DESTDIR)$(methodsdir)" "$(DESTDIR)$(perllibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-nobase_dist_methodsDATA \
+ install-nobase_dist_perllibDATA install-nobase_methodsSCRIPTS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-nobase_dist_methodsDATA \
+ uninstall-nobase_dist_perllibDATA \
+ uninstall-nobase_methodsSCRIPTS
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-nobase_dist_methodsDATA \
+ install-nobase_dist_perllibDATA install-nobase_methodsSCRIPTS \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am \
+ uninstall-nobase_dist_methodsDATA \
+ uninstall-nobase_dist_perllibDATA \
+ uninstall-nobase_methodsSCRIPTS
+
+.PRECIOUS: Makefile
+
+
+.sh: Makefile
+ @test -d `dirname $@` || $(MKDIR_P) `dirname $@`
+ $(do_shell_subst) <$< >$@
+ $(AM_V_at) chmod +x $@
+
+.pl: Makefile
+ @test -d `dirname $@` || $(MKDIR_P) `dirname $@`
+ $(do_perl_subst) <$< >$@
+ $(AM_V_at) chmod +x $@
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/mnt
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/file
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/ftp
+ $(MKDIR_P) $(DESTDIR)$(admindir)/methods/media
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/dselect/methods/file/desc.file b/dselect/methods/file/desc.file
new file mode 100644
index 0000000..5f5acf9
--- /dev/null
+++ b/dselect/methods/file/desc.file
@@ -0,0 +1,8 @@
+Installation from a directory on the filesystem.
+
+The area you are installing from should contain the Packages.gz file
+from each distribution area being installed (usually main and optionally
+contrib and non-free) as well as the corresponding binary/*/*.deb files.
+
+The easiest way to do get this is to make a (partial) copy of the
+distribution site's directory hierarchy, if possible.
diff --git a/dselect/methods/file/install.sh b/dselect/methods/file/install.sh
new file mode 100755
index 0000000..f5e3dae
--- /dev/null
+++ b/dselect/methods/file/install.sh
@@ -0,0 +1,124 @@
+#!/bin/sh
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+cd "$vardir/methods/file"
+
+. ./shvar.$option
+
+xit=1
+trap '
+ exit $xit
+' 0
+
+predep="$vardir/predep-package"
+while true; do
+ set +e
+ dpkg --admindir "$vardir" --predep-package >"$predep"
+ rc=$?
+ set -e
+ if test $rc = 1; then
+ break
+ fi
+ test $rc = 0
+
+ perl -e '
+ ($binaryprefix,$predep) = @ARGV;
+ $binaryprefix =~ s,/*$,/, if length($binaryprefix);
+ open(P, "< $predep") or die "cannot open $predep: $!\n";
+ while (<P>) {
+ s/\s*\n$//;
+ $package = $_ if s/^Package: //i;
+ @filename = split(/ /,$_) if s/^Filename: //i;
+ @msdosfilename = split(/ /,$_) if s/^MSDOS-Filename: //i;
+ }
+ die "internal error - no package" if length($package) == 0;
+ die "internal error - no filename" if not @filename;
+ die "internal error - mismatch >@filename< >@msdosfilename<"
+ if @filename && @msdosfilename &&
+ @filename != @msdosfilename;
+ @invoke = (); $| = 1;
+ for ($i = 0; $i <= $#filename; $i++) {
+ $ppart = $i+1;
+ print "Looking for part $ppart of $package ... ";
+ if (-f "$binaryprefix$filename[$i]") {
+ $print = $filename[$i];
+ $invoke = "$binaryprefix$filename[$i]";
+ } elsif (-f "$binaryprefix$msdosfilename[$i]") {
+ $print = $msdosfilename[$i];
+ $invoke = "$binaryprefix$msdosfilename[$i]";
+ } else {
+ $base = $filename[$i]; $base =~ s,.*/,,;
+ $msdosbase = $msdosfilename[$i]; $msdosbase =~ s,.*/,,;
+ $c = open(X, "-|"));
+ if (not defined $c) {
+ die "failed to fork for find: $!\n";
+ }
+ if (!$c) {
+ exec("find", "-L",
+ length($binaryprefix) ?
+ $binaryprefix : ".",
+ "-name",$base,"-o","-name",$msdosbase);
+ die "failed to exec find: $!\n";
+ }
+ while (chop($invoke = <X>)) { last if -f $invoke; }
+ $print = $invoke;
+ if (substr($print,0,length($binaryprefix)+1) eq
+ "$binaryprefix/") {
+ $print = substr($print,length($binaryprefix));
+ }
+ }
+ if (!length($invoke)) {
+ warn "
+
+Cannot find the appropriate file(s) anywhere needed to install or upgrade
+package $package. Expecting version $version or later, as listed in the
+Packages file.
+
+Perhaps the package was downloaded with an unexpected name? In any case,
+you must find the file(s) and then either place it with the correct
+filename(s) (as listed in the Packages file or in $vardir/available)
+and rerun the installation, or upgrade the package by using
+\"dpkg --install --auto-deconfigure" by hand.
+
+";
+ exit(1);
+ }
+ print "$print\n";
+ push(@invoke,$invoke);
+ }
+ print "Running dpkg -iB for $package ...\n";
+ exec("dpkg","--admindir",$vardir,"-iB","--",@invoke);
+ die "failed to exec dpkg: $!\n";
+ ' -- "$p_mountpoint$p_main_binary" "$predep"
+done
+
+for f in main ctb nf lcl; do
+ eval 'this_binary=$p_'$f'_binary'
+ if [ -z "$this_binary" ]; then
+ continue
+ fi
+ echo Running dpkg --admindir $vardir -iGROEB "$p_mountpoint$this_binary"
+ dpkg --admindir $vardir -iGROEB "$p_mountpoint$this_binary"
+done
+
+echo -n 'Installation OK. Hit RETURN. '
+read response
+
+xit=0
diff --git a/dselect/methods/file/names b/dselect/methods/file/names
new file mode 100644
index 0000000..3b36a48
--- /dev/null
+++ b/dselect/methods/file/names
@@ -0,0 +1 @@
+42 file Install from a directory in the filesystem.
diff --git a/dselect/methods/file/setup.sh b/dselect/methods/file/setup.sh
new file mode 100755
index 0000000..2f04aa2
--- /dev/null
+++ b/dselect/methods/file/setup.sh
@@ -0,0 +1,305 @@
+#!/bin/sh
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+cd "$vardir/methods/file"
+tp="$(mktemp --tmpdir $method.XXXXXXXXXX)"
+
+iarch=$(dpkg --admindir $vardir --print-architecture)
+
+xit=1
+trap '
+ rm -f $tp.?
+ exit $xit
+' 0
+
+if ls -d "$tp.?" >/dev/null 2>&1; then
+ rm $tp.?
+fi
+
+yesno () {
+ while true; do
+ echo -n "$2 [$1] "
+ read response
+ if [ -z "$response" ]; then
+ response="$1"
+ fi
+ case "$response" in
+ [Nn]*)
+ yesno=no
+ return
+ ;;
+ [Yy]*)
+ yesno=yes
+ return
+ ;;
+ esac
+ done
+}
+
+outputparam () {
+ echo "$2" | sed -e "s/'/'\\\\''/; s/^/$1='/; s/$/'/" >&3
+}
+
+intrkey="$(stty -a | sed -n 's/.*intr = \([^;]*\);.*/\1/p')"
+echo "
+If you make a mistake, use the interrupt key ($intrkey) to abort.
+"
+
+# State variables, “best first”
+# {main,ctb,nf,lcl}_{packages,binary}
+# Empty before we've found them or if they're not available,
+# set to the relevant bit under mountpoint otherwise.
+# hierbase
+# A directory containing a Debian FTP site mirror tree for ONE distribution.
+# eg /pub/debian/dists/stable
+# mountpoint
+# The mountpoint for the filesystem containing the stuff
+# empty or unset if we don't know yet, or if we haven't mounted anything;
+# may also be empty if ‘directory’ was set.
+# fstype
+# The filesystem type to use.
+
+if [ -f shvar.$option ]; then
+ . ./shvar.$option
+fi
+
+if [ -n "$mountpoint" ]; then
+ # We must have $mountpoint
+ echo \
+"All directory names should be entered relative to the root of the
+$fstype filesystem.
+"
+fi
+
+while true; do
+ echo \
+"In order to make it easy to find the relevant files, it is preferred
+to install from a straightforward copy of the Debian distribution.
+To use this, it is required to know where the top level of that copy of
+the distribution is (eg. 'debian/dists/stable') - this directory usually
+contains the Packages-Master file.
+
+If you do not have a straightforward copy of the distribution available
+just answer 'none' and each needed part will be prompted individually."
+ defhierbase=none
+ # maybe ask for debian/dists and then show and ask for available dists
+ # eg. {stable,frozen,unstable,bo,hamm,slink}
+ if [ -n "$p_hierbase" ]; then
+ if [ -d "$mountpoint/$p_hierbase/main/binary-$iarch" ]; then
+ echo "
+Last time you said '$p_hierbase', and that looks plausible."
+ defhierbase="$p_hierbase"
+ else
+ echo "
+Last time you said '$p_hierbase', but that doesn't look plausible,
+since '$p_hierbase/main/binary-$iarch' doesn't seem to exist."
+ fi
+ fi
+ if [ none = "$defhierbase" ]; then
+ if [ -d "$mountpoint/debian/dists/stable/main/binary-$iarch" ]; then
+ echo "
+'/debian/dists/stable' exists and looks plausible, so that's the default."
+ defhierbase=/debian/dists/stable
+ elif [ -d "$mountpoint/dists/stable/main/binary-$iarch" ]; then
+ echo "
+'/dists/stable' exists and looks plausible, so that's the default."
+ defhierbase=/dists/stable
+ fi
+ fi
+ echo -n \
+"Distribution top level ? [$defhierbase] "
+ read response
+ if [ -z "$response" ]; then
+ response="$defhierbase"
+ fi
+ if [ none = "$response" ]; then
+ hierbase=""
+ break
+ elif [ -d "$mountpoint/$response/main/binary-$iarch" ]; then
+ hierbase="$(echo "$response" | sed -e 's:/*$::; s:^/*:/:')"
+ break
+ fi
+ echo \
+"$response/main/binary-$iarch does not exist.
+"
+done
+
+case "$hierbase" in
+/* )
+ ;;
+'' )
+ ;;
+* )
+ hierbase="/$hierbase"
+ ;;
+esac
+
+check_binary () {
+ # args: area-in-messages directory
+ # eg: main "$hierbase/main/binary-$iarch"
+ # checks whether $2 contains *.deb
+ if ! [ -d "$mountpoint$2/" ]; then
+ echo "'$2' does not exist."
+ return
+ fi
+
+ if ! ( find -L "$mountpoint$2/" -name '*.deb' -print \
+ | head -n 1 ) 2>/dev/null | grep . >/dev/null; then
+ echo "'$2' does not contain any *.deb packages. Hmmpf."
+ return
+ fi
+ echo "Using '$2' as $1 binary dir."
+ this_binary="$2"
+}
+
+find_area () {
+ # args: area-in-messages area-in-vars subdirectory-in-hier
+ # last-time-binary last-time-packages
+ # eg: main main main
+ # "$p_main_binary" "$p_main_packages"
+
+ this_binary=''
+ this_packages=''
+ if [ -n "$hierbase" ]; then
+ check_binary $1 "$hierbase/$3/binary-$iarch"
+ fi
+
+ if [ $2 = lcl ] && [ -z "$this_binary" ]; then
+ echo "
+Note: By default there is no 'local' directory. It is intended for
+packages you made yourself."
+ fi
+ if [ $2 = nf -a -z "$this_binary" ]; then
+ echo "
+Note: most media distributions of Debian do not include programs available
+in the 'non-free' directory of the distribution site.
+This is because these programs are under licenses that do not allow source
+modification or prevent distribution for profit on a media, or other
+restrictions that make them not free software.
+If you wish to install these programs you will have to get them from an
+alternative source."
+ fi
+ while [ -z "$this_binary" ]; do
+ defaultbinary="$4"
+ echo "
+Which directory contains the *.deb packages from the $1 distribution
+area (this directory is named '$3/binary-$iarch' on the distribution site) ?
+Say 'none' if this area is not available."
+ if [ $2 != main ] && [ -z "$defaultbinary" ]; then
+ defaultbinary=none
+ fi
+ echo -n \
+"Enter _$1_ binary dir. [$4]
+ ? "
+ read response
+ if [ -z "$response" ] && [ -n "$defaultbinary" ]; then
+ response="$defaultbinary"
+ fi
+ if [ none = "$response" ]; then
+ break
+ fi
+ case "$response" in
+ '' | none)
+ continue
+ ;;
+ esac
+ check_binary $1 "$(echo "$response" | sed -e 's:/$::; s:^/*:/:')"
+ done
+ if [ -n "$this_binary" ]; then
+ for f in Packages.gz packages.gz Packages packages; do
+ if [ -f "$mountpoint/$this_binary/$f" ]; then
+ echo "Using '$this_binary/$f' for $1."
+ this_packages="$this_binary/$f"
+ break
+ fi
+ done
+ while [ -z "$this_packages" ]; do
+ echo -n "
+Cannot find the $1 'Packages' file. The information in the
+'Packages' file is important for package selection during new
+installations, and is very useful for upgrades.
+
+If you overlooked it when downloading you should do get it now and
+return to this installation procedure when you have done so: you will
+find one Packages file and one Packages.gz file -- either will do --
+in the 'binary-$iarch' subdirectory of each area on the FTP sites and
+CD-ROMs. Alternatively (and this will be rather slow) the packages in
+the distribution area can be scanned - say 'scan' if you want to do so.
+
+You need a separate Packages file from each of the distribution areas
+you wish to install.
+
+Where is the _$1_ 'Packages' file (if none is available, say 'none')
+[$5]
+ ? "
+ read response
+ if [ -z "$response" ] && [ -n "$5" ]; then
+ response="$5"
+ fi
+ case "$response" in
+ '')
+ continue
+ ;;
+ none)
+ break
+ ;;
+ scan)
+ this_packages=scan
+ ;;
+ /*)
+ this_packages="$response"
+ ;;
+ *)
+ this_packages="/$response"
+ ;;
+ esac
+ done
+ fi
+ eval $2'_binary="$this_binary"'
+ eval $2'_packages="$this_packages"'
+}
+
+find_area main main main "$p_main_binary" "$p_main_packages"
+find_area contrib ctb contrib "$p_ctb_binary" "$p_ctb_packages"
+find_area non-free nf non-free "$p_nf_binary" "$p_nf_packages"
+find_area local lcl local "$p_lcl_binary" "$p_lcl_packages"
+
+echo -n '
+Hit RETURN to continue. '
+read response
+
+exec 3>shvar.$option.new
+
+outputparam p_fstype "$fstype"
+outputparam p_mountpoint "$mountpoint"
+outputparam p_hierbase "$hierbase"
+
+outputparam p_main_packages "$main_packages"
+outputparam p_main_binary "$main_binary"
+outputparam p_ctb_packages "$ctb_packages"
+outputparam p_ctb_binary "$ctb_binary"
+outputparam p_nf_packages "$nf_packages"
+outputparam p_nf_binary "$nf_binary"
+outputparam p_lcl_packages "$lcl_packages"
+outputparam p_lcl_binary "$lcl_binary"
+
+mv shvar.$option.new shvar.$option
+
+xit=0
diff --git a/dselect/methods/file/update.sh b/dselect/methods/file/update.sh
new file mode 100755
index 0000000..c0937cc
--- /dev/null
+++ b/dselect/methods/file/update.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+cd "$vardir/methods/file"
+
+. ./shvar.$option
+
+if [ -z "$p_main_packages" ] && [ -z "$p_ctb_packages" ] && \
+ [ -z "$p_nf_packages" ] && [ -z "$p_lcl_packages" ]; then
+ echo '
+No Packages files available, cannot update available packages list.
+Hit RETURN to continue. '
+ read response
+ exit 0
+fi
+
+xit=1
+trap '
+ rm -f packages-main packages-ctb packages-nf packages-lcl
+ exit $xit
+' 0
+
+updatetype=update
+
+for f in main ctb nf lcl; do
+ eval 'this_packages=$p_'$f'_packages'
+ case "$this_packages" in
+ '')
+ continue
+ ;;
+ scan)
+ eval 'this_binary=$p_'$f'_binary'
+ if [ -z "$this_binary" ]; then
+ continue
+ fi
+ if [ "$updatetype" = update ]; then
+ dpkg --admindir $vardir --clear-avail
+ updatetype=merge
+ fi
+ echo Running dpkg --record-avail -R "$p_mountpoint$this_binary"
+ dpkg --admindir $vardir --record-avail -R "$p_mountpoint$this_binary"
+ ;;
+ *)
+ packagesfile="$p_mountpoint$this_packages"
+ case "$packagesfile" in
+ *.gz | *.Z | *.GZ | *.z)
+ echo -n "Uncompressing $packagesfile ... "
+ zcat <"$packagesfile" >packages-$f
+ echo done.
+ dpkg --admindir $vardir --$updatetype-avail packages-$f
+ updatetype=merge
+ ;;
+ '')
+ ;;
+ *)
+ dpkg --admindir $vardir --$updatetype-avail "$packagesfile"
+ updatetype=merge
+ ;;
+ esac
+ ;;
+ esac
+done
+
+echo -n 'Update OK. Hit RETURN. '
+read response
+
+xit=0
diff --git a/dselect/methods/ftp/desc.ftp b/dselect/methods/ftp/desc.ftp
new file mode 100644
index 0000000..accd994
--- /dev/null
+++ b/dselect/methods/ftp/desc.ftp
@@ -0,0 +1,2 @@
+Installation using ftp, you must know one (or more) ftp site(s) and the
+correct directories for the Debian distribution.
diff --git a/dselect/methods/ftp/install.pl b/dselect/methods/ftp/install.pl
new file mode 100755
index 0000000..64af2ee
--- /dev/null
+++ b/dselect/methods/ftp/install.pl
@@ -0,0 +1,624 @@
+#!/usr/bin/perl
+#
+# Copyright © 1996 Andy Guy <awpguy@acs.ucalgary.ca>
+# Copyright © 1998 Martin Schulze <joey@infodrom.north.de>
+# Copyright © 1999, 2009 Raphaël Hertzog <hertzog@debian.org>
+#
+# 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; version 2 of the License.
+#
+# 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, see <https://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+
+use File::Path qw(make_path remove_tree);
+use File::Basename;
+
+eval q{
+ pop @INC if $INC[-1] eq '.';
+ use File::Find;
+ use Data::Dumper;
+
+ use Dpkg::File;
+};
+if ($@) {
+ warn "Missing Dpkg modules required by the FTP access method.\n\n";
+ exit 1;
+}
+
+use Dselect::Ftp;
+
+my $ftp;
+
+# exit value
+my $exit = 0;
+
+# deal with arguments
+my $vardir = $ARGV[0];
+my $method = $ARGV[1];
+my $option = $ARGV[2];
+
+if ($option eq 'manual') {
+ print "manual mode not supported yet\n";
+ exit 1;
+}
+#print "vardir: $vardir, method: $method, option: $option\n";
+
+my $methdir = "$vardir/methods/ftp";
+
+# get info from control file
+read_config("$methdir/vars");
+
+chdir "$methdir";
+make_path("$methdir/$CONFIG{dldir}", { mode => 0755 });
+
+
+#Read md5sums already calculated
+my %md5sums;
+if (-f "$methdir/md5sums") {
+ my $code = file_slurp("$methdir/md5sums");
+ my $VAR1; ## no critic (Variables::ProhibitUnusedVariables)
+ my $res = eval $code;
+ if ($@) {
+ die "couldn't eval $methdir/md5sums content: $@\n";
+ }
+ if (ref($res)) { %md5sums = %{$res} }
+}
+
+# Get a stanza.
+# returns a ref to a hash containing flds->fld contents
+# white space from the ends of lines is removed and newlines added
+# (no trailing newline).
+# die's if something unexpected happens
+sub get_stanza {
+ my $fh = shift;
+ my %flds;
+ my $fld;
+ while (<$fh>) {
+ if (length != 0) {
+ FLDLOOP: while (1) {
+ if ( /^(\S+):\s*(.*)\s*$/ ) {
+ $fld = lc($1);
+ $flds{$fld} = $2;
+ while (<$fh>) {
+ if (length == 0) {
+ return %flds;
+ } elsif ( /^(\s.*)$/ ) {
+ $flds{$fld} = $flds{$fld} . "\n" . $1;
+ } else {
+ next FLDLOOP;
+ }
+ }
+ return %flds;
+ } else {
+ die "expected a start of field line, but got:\n$_";
+ }
+ }
+ }
+ }
+ return %flds;
+}
+
+# process status file
+# create curpkgs hash with version (no version implies not currently installed)
+# of packages we want
+print "Processing status file...\n";
+my %curpkgs;
+sub procstatus {
+ my (%flds, $fld);
+ open(my $status_fh, '<', "$vardir/status") or
+ die 'Could not open status file';
+ while (%flds = get_stanza($status_fh), %flds) {
+ if($flds{'status'} =~ /^install ok/) {
+ my $cs = (split(/ /, $flds{'status'}))[2];
+ if (($cs eq 'not-installed') ||
+ ($cs eq 'half-installed') ||
+ ($cs eq 'config-files')) {
+ $curpkgs{$flds{'package'}} = '';
+ } else {
+ $curpkgs{$flds{'package'}} = $flds{'version'};
+ }
+ }
+ }
+ close($status_fh);
+}
+procstatus();
+
+sub dcmpvers {
+ my($a, $p, $b) = @_;
+ my ($r);
+ $r = system('dpkg', '--compare-versions', "$a", "$p", "$b");
+ $r = $r/256;
+ if ($r == 0) {
+ return 1;
+ } elsif ($r == 1) {
+ return 0;
+ }
+ die "dpkg --compare-versions $a $p $b - failed with $r";
+}
+
+# process package files, looking for packages to install
+# create a hash of these packages pkgname => version, filenames...
+# filename => md5sum, size
+# for all packages
+my %pkgs;
+my %pkgfiles;
+sub procpkgfile {
+ my $fn = shift;
+ my $site = shift;
+ my $dist = shift;
+ my (@files, @sizes, @md5sums, $pkg, $ver, $nfs, $fld);
+ my(%flds);
+ open(my $pkgfile_fh, '<', $fn) or die "could not open package file $fn";
+ while (%flds = get_stanza($pkgfile_fh), %flds) {
+ $pkg = $flds{'package'};
+ $ver = $curpkgs{$pkg};
+ @files = split(/[\s\n]+/, $flds{'filename'});
+ @sizes = split(/[\s\n]+/, $flds{'size'});
+ @md5sums = split(/[\s\n]+/, $flds{'md5sum'});
+ if (defined($ver) && (($ver eq '') || dcmpvers($ver, 'lt', $flds{'version'}))) {
+ $pkgs{$pkg} = [ $flds{'version'}, [ @files ], $site ];
+ $curpkgs{$pkg} = $flds{'version'};
+ }
+ $nfs = scalar(@files);
+ if(($nfs != scalar(@sizes)) || ($nfs != scalar(@md5sums)) ) {
+ print "Different number of filenames, sizes and md5sums for $flds{'package'}\n";
+ } else {
+ my $i = 0;
+ foreach my $fl (@files) {
+ $pkgfiles{$fl} = [ $md5sums[$i], $sizes[$i], $site, $dist ];
+ $i++;
+ }
+ }
+ }
+ close $pkgfile_fh or die "cannot close package file $fn: $!\n";
+}
+
+print "\nProcessing Package files...\n";
+my ($fn, $i, $j);
+$i = 0;
+foreach my $site (@{$CONFIG{site}}) {
+ $j = 0;
+ foreach my $dist (@{$site->[2]}) {
+ $fn = $dist;
+ $fn =~ tr#/#_#;
+ $fn = "Packages.$site->[0].$fn";
+ if (-f $fn) {
+ print " $site->[0] $dist...\n";
+ procpkgfile($fn,$i,$j);
+ } else {
+ print "Could not find packages file for $site->[0] $dist distribution (re-run Update)\n"
+ }
+ $j++;
+ }
+ $i++;
+}
+
+my $dldir = $CONFIG{dldir};
+# md5sum
+sub md5sum($) {
+ my $fn = shift;
+ my $m = qx(md5sum $fn);
+ $m = (split(' ', $m))[0];
+ $md5sums{"$dldir/$fn"} = $m;
+ return $m;
+}
+
+# construct list of files to get
+# hash of filenames => size of downloaded part
+# query user for each partial file
+print "\nConstructing list of files to get...\n";
+my %downloads;
+my ($dir, @info, @files, $csize, $size);
+my $totsize = 0;
+foreach my $pkg (keys(%pkgs)) {
+ @files = @{$pkgs{$pkg}[1]};
+ foreach my $fn (@files) {
+ #Look for a partial file
+ if (-f "$dldir/$fn.partial") {
+ rename "$dldir/$fn.partial", "$dldir/$fn";
+ }
+ $dir = dirname($fn);
+ if(! -d "$dldir/$dir") {
+ make_path("$dldir/$dir", { mode => 0755 });
+ }
+ @info = @{$pkgfiles{$fn}};
+ $csize = int($info[1]/1024)+1;
+ if(-f "$dldir/$fn") {
+ $size = -s "$dldir/$fn";
+ if($info[1] > $size) {
+ # partial download
+ if (yesno('y', "continue file: $fn (" . nb($size) . '/' .
+ nb($info[1]) . ')')) {
+ $downloads{$fn} = $size;
+ $totsize += $csize - int($size/1024);
+ } else {
+ $downloads{$fn} = 0;
+ $totsize += $csize;
+ }
+ } else {
+ # check md5sum
+ if (! exists $md5sums{"$dldir/$fn"}) {
+ $md5sums{"$dldir/$fn"} = md5sum("$dldir/$fn");
+ }
+ if ($md5sums{"$dldir/$fn"} eq $info[0]) {
+ print "already got: $fn\n";
+ } else {
+ print "corrupted: $fn\n";
+ $downloads{$fn} = 0;
+ }
+ }
+ } else {
+ my $ffn = $fn;
+ $ffn =~ s/binary-[^\/]+/.../;
+ print 'want: ' .
+ $CONFIG{site}[$pkgfiles{$fn}[2]][0] . " $ffn (${csize}k)\n";
+ $downloads{$fn} = 0;
+ $totsize += $csize;
+ }
+ }
+}
+
+my $avsp = qx(df -Pk $dldir| awk '{ print \$4}' | tail -n 1);
+chomp $avsp;
+
+print "\nApproximate total space required: ${totsize}k\n";
+print "Available space in $dldir: ${avsp}k\n";
+
+#$avsp = qx(df -k $::dldir| paste -s | awk '{ print \$11});
+#chomp $avsp;
+
+if($totsize == 0) {
+ print 'Nothing to get.';
+} else {
+ if($totsize > $avsp) {
+ print "Space required is greater than available space,\n";
+ print "you will need to select which items to get.\n";
+ }
+# ask user which files to get
+ if (($totsize > $avsp) ||
+ yesno('n', 'Do you want to select the files to get')) {
+ $totsize = 0;
+ my @files = sort(keys(%downloads));
+ my $def = 'y';
+ foreach my $fn (@files) {
+ my @info = @{$pkgfiles{$fn}};
+ my $csize = int($info[1] / 1024) + 1;
+ my $rsize = int(($info[1] - $downloads{$fn}) / 1024) + 1;
+ if ($rsize + $totsize > $avsp) {
+ print "no room for: $fn\n";
+ delete $downloads{$fn};
+ } else {
+ if(yesno($def, $downloads{$fn}
+ ? "download: $fn ${rsize}k/${csize}k (total = ${totsize}k)"
+ : "download: $fn ${rsize}k (total = ${totsize}k)")) {
+ $def = 'y';
+ $totsize += $rsize;
+ } else {
+ $def = 'n';
+ delete $downloads{$fn};
+ }
+ }
+ }
+ }
+}
+
+sub download() {
+ my $i = 0;
+
+ foreach my $site (@{$CONFIG{site}}) {
+ my @getfiles = grep { $pkgfiles{$_}[2] == $i } keys %downloads;
+ my @pre_dist = (); # Directory to add before $fn
+
+ #Scan distributions for looking at "(../)+/dir/dir"
+ my ($n,$cp);
+ $cp = -1;
+ foreach (@{$site->[2]}) {
+ $cp++;
+ $pre_dist[$cp] = '';
+ $n = (s{\.\./}{../}g);
+ next if (! $n);
+ if (m<^((?:\.\./){$n}(?:[^/]+/){$n})>) {
+ $pre_dist[$cp] = $1;
+ }
+ }
+
+ if (! @getfiles) { $i++; next; }
+
+ $ftp = do_connect(ftpsite => $site->[0],
+ ftpdir => $site->[1],
+ passive => $site->[3],
+ username => $site->[4],
+ password => $site->[5],
+ useproxy => $CONFIG{use_auth_proxy},
+ proxyhost => $CONFIG{proxyhost},
+ proxylogname => $CONFIG{proxylogname},
+ proxypassword => $CONFIG{proxypassword});
+
+ local $SIG{INT} = sub { die "Interrupted !\n"; };
+
+ my ($rsize, $res, $pre);
+ foreach my $fn (@getfiles) {
+ $pre = $pre_dist[$pkgfiles{$fn}[3]] || '';
+ if ($downloads{$fn}) {
+ $rsize = ${pkgfiles{$fn}}[1] - $downloads{$fn};
+ print "getting: $pre$fn (" . nb($rsize) . '/' .
+ nb($pkgfiles{$fn}[1]) . ")\n";
+ } else {
+ print "getting: $pre$fn (". nb($pkgfiles{$fn}[1]) . ")\n";
+ }
+ $res = $ftp->get("$pre$fn", "$dldir/$fn", $downloads{$fn});
+ if(! $res) {
+ my $r = $ftp->code();
+ print $ftp->message() . "\n";
+ if (!($r == 550 || $r == 450)) {
+ return 1;
+ } else {
+ #Try to find another file or this package
+ print "Looking for another version of the package...\n";
+ my ($dir, $package) = ($fn =~ m{^(.*)/([^/]+)_[^/]+.deb$});
+ my $list = $ftp->ls("$pre$dir");
+ if ($ftp->ok() && ref($list)) {
+ foreach my $file (@{$list}) {
+ if ($file =~ m/($dir\/\Q$package\E_[^\/]+.deb)/i) {
+ print "Package found : $file\n";
+ print "getting: $file (size not known)\n";
+ $res = $ftp->get($file, "$dldir/$1");
+ if (! $res) {
+ $r = $ftp->code();
+ print $ftp->message() . "\n";
+ return 1 if ($r != 550 and $r != 450);
+ }
+ }
+ }
+ }
+ }
+ }
+ # fully got, remove it from list in case we have to re-download
+ delete $downloads{$fn};
+ }
+ $ftp->quit();
+ $i++;
+ }
+ return 0;
+}
+
+# download stuff (protect from ^C)
+if($totsize != 0) {
+ if (yesno('y', "\nDo you want to download the required files")) {
+ DOWNLOAD_TRY: while (1) {
+ print "Downloading files... use ^C to stop\n";
+ eval {
+ if ((download() == 1) &&
+ yesno('y', "\nDo you want to retry downloading at once")) {
+ next DOWNLOAD_TRY;
+ }
+ };
+ if($@ =~ /Interrupted|Timeout/i ) {
+ # close the FTP connection if needed
+ if ((ref($ftp) =~ /Net::FTP/) and ($@ =~ /Interrupted/i)) {
+ $ftp->abort();
+ $ftp->quit();
+ undef $ftp;
+ }
+ print "FTP ERROR\n";
+ if (yesno('y', "\nDo you want to retry downloading at once")) {
+ # get the first $fn that foreach would give:
+ # this is the one that got interrupted.
+ MY_ITER: foreach my $ffn (keys(%downloads)) {
+ $fn = $ffn;
+ last MY_ITER;
+ }
+ my $size = -s "$dldir/$fn";
+ # partial download
+ if (yesno('y', "continue file: $fn (at $size)")) {
+ $downloads{$fn} = $size;
+ } else {
+ $downloads{$fn} = 0;
+ }
+ next DOWNLOAD_TRY;
+ } else {
+ $exit = 1;
+ last DOWNLOAD_TRY;
+ }
+ } elsif ($@) {
+ print "An error occurred ($@) : stopping download\n";
+ }
+ last DOWNLOAD_TRY;
+ }
+ }
+}
+
+# remove duplicate packages (keep latest versions)
+# move half downloaded files out of the way
+# delete corrupted files
+print "\nProcessing downloaded files...(for corrupt/old/partial)\n";
+my %vers; # package => version
+my %files; # package-version => files...
+
+# check a deb or split deb file
+# return 1 if it a deb file, 2 if it is a split deb file
+# else 0
+sub chkdeb($) {
+ my ($fn) = @_;
+ # check to see if it is a .deb file
+ if(!system("dpkg-deb --info $fn 2>&1 >/dev/null && dpkg-deb --contents $fn 2>&1 >/dev/null")) {
+ return 1;
+ } elsif(!system("dpkg-split --info $fn 2>&1 >/dev/null")) {
+ return 2;
+ }
+ return 0;
+}
+sub getdebinfo($) {
+ my ($fn) = @_;
+ my $type = chkdeb($fn);
+ my ($pkg, $ver);
+ if($type == 1) {
+ open(my $pkgfile_fh, '-|', "dpkg-deb --field $fn")
+ or die "cannot create pipe for 'dpkg-deb --field $fn'";
+ my %fields = get_stanza($pkgfile_fh);
+ close($pkgfile_fh);
+ $pkg = $fields{'package'};
+ $ver = $fields{'version'};
+ return $pkg, $ver;
+ } elsif ( $type == 2) {
+ open(my $pkgfile_fh, '-|', "dpkg-split --info $fn")
+ or die "cannot create pipe for 'dpkg-split --info $fn'";
+ while (<$pkgfile_fh>) {
+ /Part of package:\s*(\S+)/ and $pkg = $1;
+ /\.\.\. version:\s*(\S+)/ and $ver = $1;
+ }
+ close($pkgfile_fh);
+ return $pkg, $ver;
+ }
+ print "could not figure out type of $fn\n";
+ return $pkg, $ver;
+}
+
+# process deb file to make sure we only keep latest versions
+sub prcdeb($$) {
+ my ($dir, $fn) = @_;
+ my ($pkg, $ver) = getdebinfo($fn);
+ if(!defined($pkg) || !defined($ver)) {
+ print "could not get package info from file\n";
+ return 0;
+ }
+ if($vers{$pkg}) {
+ if (dcmpvers($vers{$pkg}, 'eq', $ver)) {
+ $files{$pkg . $ver} = [ $files{$pkg . $ver }, "$dir/$fn" ];
+ } elsif (dcmpvers($vers{$pkg}, 'gt', $ver)) {
+ print "old version\n";
+ unlink $fn;
+ } else { # else $ver is gt current version
+ foreach my $c (@{$files{$pkg . $vers{$pkg}}}) {
+ print "replaces: $c\n";
+ unlink "$vardir/methods/ftp/$dldir/$c";
+ }
+ $vers{$pkg} = $ver;
+ $files{$pkg . $ver} = [ "$dir/$fn" ];
+ }
+ } else {
+ $vers{$pkg} = $ver;
+ $files{$pkg . $ver} = [ "$dir/$fn" ];
+ }
+}
+
+sub prcfile() {
+ my ($fn) = $_;
+ if (-f $fn and $fn ne '.') {
+ my $dir = '.';
+ if (length($File::Find::dir) > length($dldir)) {
+ $dir = substr($File::Find::dir, length($dldir)+1);
+ }
+ print "$dir/$fn\n";
+ if(defined($pkgfiles{"$dir/$fn"})) {
+ my @info = @{$pkgfiles{"$dir/$fn"}};
+ my $size = -s $fn;
+ if($size == 0) {
+ print "zero length file\n";
+ unlink $fn;
+ } elsif($size < $info[1]) {
+ print "partial file\n";
+ rename $fn, "$fn.partial";
+ } elsif(( (exists $md5sums{"$dldir/$fn"})
+ and ($md5sums{"$dldir/$fn"} ne $info[0]) )
+ or
+ (md5sum($fn) ne $info[0])) {
+ print "corrupt file\n";
+ unlink $fn;
+ } else {
+ prcdeb($dir, $fn);
+ }
+ } elsif($fn =~ /.deb$/) {
+ if(chkdeb($fn)) {
+ prcdeb($dir, $fn);
+ } else {
+ print "corrupt file\n";
+ unlink $fn;
+ }
+ } else {
+ print "non-debian file\n";
+ }
+ }
+}
+find(\&prcfile, "$dldir/");
+
+# install .debs
+if (yesno('y', "\nDo you want to install the files fetched")) {
+ print "Installing files...\n";
+ #Installing pre-dependent package before !
+ my (@flds, $package, @filename, $r);
+ while (@flds = qx(dpkg --predep-package), $? == 0) {
+ foreach my $field (@flds) {
+ $field =~ s/\s*\n//;
+ $package = $field if $field =~ s/^Package: //i;
+ @filename = split / +/, $field if $field =~ s/^Filename: //i;
+ }
+ @filename = map { "$dldir/$_" } @filename;
+ next if (! @filename);
+ $r = system('dpkg', '-iB', '--', @filename);
+ if ($r) { print "DPKG ERROR\n"; $exit = 1; }
+ }
+ #Installing other packages after
+ $r = system('dpkg', '-iGREOB', $dldir);
+ if($r) {
+ print "DPKG ERROR\n";
+ $exit = 1;
+ }
+}
+
+sub removeinstalled {
+ my $fn = $_;
+ if (-f $fn and $fn ne '.') {
+ my $dir = '.';
+ if (length($File::Find::dir) > length($dldir)) {
+ $dir = substr($File::Find::dir, length($dldir)+1);
+ }
+ if($fn =~ /.deb$/) {
+ my($pkg, $ver) = getdebinfo($fn);
+ if(!defined($pkg) || !defined($ver)) {
+ print "Could not get info for: $dir/$fn\n";
+ } else {
+ if ($curpkgs{$pkg} and dcmpvers($ver, 'le', $curpkgs{$pkg})) {
+ print "deleting: $dir/$fn\n";
+ unlink $fn;
+ } else {
+ print "leaving: $dir/$fn\n";
+ }
+ }
+ } else {
+ print "non-debian: $dir/$fn\n";
+ }
+ }
+}
+
+# remove .debs that have been installed (query user)
+# first need to reprocess status file
+if (yesno('y', "\nDo you wish to delete the installed package (.deb) files?")) {
+ print "Removing installed files...\n";
+ %curpkgs = ();
+ procstatus();
+ find(\&removeinstalled, "$dldir/");
+}
+
+# remove whole ./debian directory if user wants to
+if (yesno('n', "\nDo you want to remove $dldir directory?")) {
+ remove_tree($dldir);
+}
+
+#Store useful md5sums
+foreach my $file (keys %md5sums) {
+ next if -f $file;
+ delete $md5sums{$file};
+}
+file_dump("$methdir/md5sums", Dumper(\%md5sums));
+
+exit $exit;
diff --git a/dselect/methods/ftp/names b/dselect/methods/ftp/names
new file mode 100644
index 0000000..6499279
--- /dev/null
+++ b/dselect/methods/ftp/names
@@ -0,0 +1 @@
+60 ftp Install using ftp.
diff --git a/dselect/methods/ftp/setup.pl b/dselect/methods/ftp/setup.pl
new file mode 100755
index 0000000..3376b48
--- /dev/null
+++ b/dselect/methods/ftp/setup.pl
@@ -0,0 +1,177 @@
+#!/usr/bin/perl
+#
+# Copyright © 1996 Andy Guy <awpguy@acs.ucalgary.ca>
+# Copyright © 1998 Martin Schulze <joey@infodrom.north.de>
+# Copyright © 1999, 2009 Raphaël Hertzog <hertzog@debian.org>
+#
+# 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; version 2 of the License.
+#
+# 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, see <https://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+
+eval q{
+ pop @INC if $INC[-1] eq '.';
+
+ use Dpkg; # Dummy import to require the presence of Dpkg::*.
+};
+if ($@) {
+ warn "Missing Dpkg modules required by the FTP access method.\n\n";
+ exit 1;
+}
+
+use Dselect::Ftp;
+
+# deal with arguments
+my $vardir = $ARGV[0];
+my $method = $ARGV[1];
+my $option = $ARGV[2];
+
+if ($option eq 'manual') {
+ print "Manual package installation.\n";
+ exit 0;
+}
+#print "vardir: $vardir, method: $method, option: $option\n";
+
+#Defaults
+my $arch = qx(dpkg --print-architecture);
+$arch = 'i386' if $?;
+chomp $arch;
+
+my $logname = qx(whoami);
+chomp $logname;
+my $host = qx(cat /etc/mailname || dnsdomainname);
+chomp $host;
+
+$CONFIG{dldir} = 'debian';
+$CONFIG{use_auth_proxy} = 0;
+$CONFIG{proxyhost} = '';
+$CONFIG{proxylogname} = $logname;
+$CONFIG{proxypassword} = '';
+
+my $methdir = "$vardir/methods/ftp";
+my $exit = 0;
+my $problem = 0;
+
+if (-f "$methdir/vars") {
+ read_config("$methdir/vars");
+}
+
+chdir "$methdir";
+if (! -d 'debian') {
+ mkdir 'debian', 0755;
+}
+# get info from user
+
+$| = 1;
+
+print <<"EOM";
+
+You must supply an ftp site, use of passive mode, username, password,
+path to the debian directory,list of distributions you are interested
+in and place to download the binary package files to (relative to
+/var/lib/dpkg/methods/ftp). You can add as much sites as you like. Later
+entries will always override older ones.
+
+Supply "?" as a password to be asked each time you connect.
+
+Eg: ftp site: ftp.debian.org
+ passive: y
+ username: anonymous
+ password: $logname\@$host
+ ftp dir: /debian
+ distributions: dists/stable/main dists/stable/contrib
+ download dir: debian
+
+You may have to use an authenticated FTP proxy in order to reach the
+FTP site:
+
+Eg: use auth proxy: y
+ proxy: proxy.isp.com
+ proxy account: $CONFIG{proxylogname}
+ proxy password: ?
+EOM
+
+if (! $CONFIG{done}) {
+ view_mirrors() if (yesno('y', 'Would you like to see a list of ftp mirrors'));
+ add_site();
+}
+edit_config($methdir);
+
+my $ftp;
+sub download() {
+ foreach (@{$CONFIG{site}}) {
+ $ftp = do_connect(ftpsite => $_->[0],
+ ftpdir => $_->[1],
+ passive => $_->[3],
+ username => $_->[4],
+ password => $_->[5],
+ useproxy => $CONFIG{use_auth_proxy},
+ proxyhost => $CONFIG{proxyhost},
+ proxylogname => $CONFIG{proxylogname},
+ proxypassword => $CONFIG{proxypassword});
+
+ my @dists = @{$_->[2]};
+
+ foreach my $dist (@dists) {
+ my $dir = "$dist/binary-$arch";
+ print "Checking $dir...\n";
+# if (!$ftp->pasv()) { print $ftp->message . "\n"; die 'error'; }
+ my @dirlst = $ftp->ls("$dir/");
+ my $got_pkgfile = 0;
+
+ foreach my $line (@dirlst) {
+ if($line =~ /Packages/) {
+ $got_pkgfile = 1;
+ }
+ }
+ if( !$got_pkgfile) {
+ print "Warning: Could not find a Packages file in $dir\n",
+ "This may not be a problem if the directory is a symbolic link\n";
+ $problem = 1;
+ }
+ }
+ print "Closing ftp connection...\n";
+ $ftp->quit();
+ }
+}
+
+# download stuff (protect from ^C)
+print "\nUsing FTP to check directories...(stop with ^C)\n\n";
+eval {
+ local $SIG{INT} = sub {
+ die "interrupted!\n";
+ };
+ download();
+};
+if($@) {
+ $ftp->quit();
+ print 'FTP ERROR - ';
+ if ($@ eq 'connect') {
+ print "config was untested\n";
+ } else {
+ print "$@\n";
+ }
+ $exit = 1;
+};
+
+# output new vars file
+$CONFIG{done} = 1;
+store_config("$methdir/vars");
+chmod 0600, "$methdir/vars";
+
+if($exit || $problem) {
+ print "Press <enter> to continue\n";
+ <STDIN>;
+}
+
+exit $exit;
diff --git a/dselect/methods/ftp/update.pl b/dselect/methods/ftp/update.pl
new file mode 100755
index 0000000..30b79a7
--- /dev/null
+++ b/dselect/methods/ftp/update.pl
@@ -0,0 +1,250 @@
+#!/usr/bin/perl
+#
+# Copyright © 1996 Andy Guy <awpguy@acs.ucalgary.ca>
+# Copyright © 1998 Martin Schulze <joey@infodrom.north.de>
+# Copyright © 1999, 2009 Raphaël Hertzog <hertzog@debian.org>
+#
+# 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; version 2 of the License.
+#
+# 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, see <https://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+
+eval q{
+ pop @INC if $INC[-1] eq '.';
+
+ use Dpkg; # Dummy import to require the presence of Dpkg::*.
+};
+if ($@) {
+ warn "Missing Dpkg modules required by the FTP access method.\n\n";
+ exit 1;
+}
+
+use Dselect::Ftp;
+
+# deal with arguments
+my $vardir = $ARGV[0];
+my $method = $ARGV[1];
+my $option = $ARGV[2];
+
+if ($option eq 'manual') {
+ print "Enter package file names or a blank line to finish\n";
+ while(1) {
+ print 'Enter package file name:';
+ my $fn = <STDIN>;
+ chomp $fn;
+ if ($fn eq '') {
+ exit 0;
+ }
+ if ( -f $fn ) {
+ system('dpkg', '--merge-avail', $fn);
+ } else {
+ print "Could not find $fn, try again\n";
+ }
+ };
+};
+
+#print "vardir: $vardir, method: $method, option: $option\n";
+
+my $arch = qx(dpkg --print-architecture);
+$arch = 'i386' if $?;
+chomp $arch;
+my $exit = 0;
+
+# get info from control file
+read_config("$vardir/methods/ftp/vars");
+
+chdir "$vardir/methods/ftp";
+
+print "Getting Packages files...(stop with ^C)\n\n";
+
+my @pkgfiles;
+my $ftp;
+my $packages_modified = 0;
+
+sub download {
+foreach (@{$CONFIG{site}}) {
+ my $site = $_;
+
+ $ftp = do_connect(ftpsite => $_->[0],
+ ftpdir => $_->[1],
+ passive => $_->[3],
+ username => $_->[4],
+ password => $_->[5],
+ useproxy => $CONFIG{use_auth_proxy},
+ proxyhost => $CONFIG{proxyhost},
+ proxylogname => $CONFIG{proxylogname},
+ proxypassword => $CONFIG{proxypassword});
+
+ my @dists = @{$_->[2]};
+ PACKAGE:
+ foreach my $dist (@dists) {
+ my $dir = "$dist/binary-$arch";
+ my $must_get = 0;
+ my $newest_pack_date;
+
+ # check existing Packages on remote site
+ print "\nChecking for Packages file... ";
+ $newest_pack_date = do_mdtm ($ftp, "$dir/Packages.gz");
+ if (defined $newest_pack_date) {
+ print "$dir/Packages.gz\n";
+ } else {
+ $dir = "$dist";
+ $newest_pack_date = do_mdtm ($ftp, "$dir/Packages.gz");
+ if (defined $newest_pack_date) {
+ print "$dir/Packages.gz\n";
+ } else {
+ print "Couldn't find Packages.gz in $dist/binary-$arch or $dist; ignoring.\n";
+ print "Your setup is probably wrong, check the distributions directories,\n";
+ print "and try with passive mode enabled/disabled (if you use a proxy/firewall)\n";
+ next PACKAGE;
+ }
+ }
+
+ # we now have $dir set to point to an existing Packages.gz file
+
+ # check if we already have a Packages file (and get its date)
+ $dist =~ tr/\//_/;
+ my $file = "Packages.$site->[0].$dist";
+
+ # if not
+ if (! -f $file) {
+ # must get one
+# print "No Packages here; must get it.\n";
+ $must_get = 1;
+ } else {
+ # else check last modification date
+ my @pack_stat = stat($file);
+ if($newest_pack_date > $pack_stat[9]) {
+# print "Packages has changed; must get it.\n";
+ $must_get = 1;
+ } elsif ($newest_pack_date < $pack_stat[9]) {
+ print " Our file is newer than theirs; skipping.\n";
+ } else {
+ print " Already up-to-date; skipping.\n";
+ }
+ }
+
+ if ($must_get) {
+ -f 'Packages.gz' and unlink 'Packages.gz';
+ -f 'Packages' and unlink 'Packages';
+ my $size = 0;
+
+ TRY_GET_PACKAGES:
+ while (1) {
+ if ($size) {
+ print ' Continuing ';
+ } else {
+ print ' Getting ';
+ }
+ print "Packages file from $dir...\n";
+ eval {
+ if ($ftp->get("$dir/Packages.gz", 'Packages.gz', $size)) {
+ if (system('gunzip', 'Packages.gz')) {
+ print " Couldn't gunzip Packages.gz, stopped";
+ die 'error';
+ }
+ } else {
+ print " Couldn't get Packages.gz from $dir !!! Stopped.";
+ die 'error';
+ }
+ };
+ if ($@) {
+ $size = -s 'Packages.gz';
+ if (ref($ftp)) {
+ $ftp->abort();
+ $ftp->quit();
+ };
+ if (yesno ('y', "Transfer failed at $size: retry at once")) {
+ $ftp = do_connect(ftpsite => $site->[0],
+ ftpdir => $site->[1],
+ passive => $site->[3],
+ username => $site->[4],
+ password => $site->[5],
+ useproxy => $CONFIG{use_auth_proxy},
+ proxyhost => $CONFIG{proxyhost},
+ proxylogname => $CONFIG{proxylogname},
+ proxypassword => $CONFIG{proxypassword});
+
+ if ($newest_pack_date != do_mdtm ($ftp, "$dir/Packages.gz")) {
+ print ("Packages file has changed !\n");
+ $size = 0;
+ }
+ next TRY_GET_PACKAGES;
+ } else {
+ die 'error';
+ }
+ }
+ last TRY_GET_PACKAGES;
+ }
+
+ if (!rename 'Packages', "Packages.$site->[0].$dist") {
+ print " Couldn't rename Packages to Packages.$site->[0].$dist";
+ die 'error';
+ } else {
+ # set local Packages file to same date as the one it mirrors
+ # to allow comparison to work.
+ utime $newest_pack_date, $newest_pack_date, "Packages.$site->[0].$dist";
+ $packages_modified = 1;
+ }
+ }
+ push @pkgfiles, "Packages.$site->[0].$dist";
+ }
+ $ftp->quit();
+ }
+}
+
+eval {
+ local $SIG{INT} = sub {
+ die "interrupted!\n";
+ };
+ download();
+};
+if($@) {
+ $ftp->quit() if (ref($ftp));
+ if($@ =~ /timeout/i) {
+ print "FTP TIMEOUT\n";
+ } else {
+ print "FTP ERROR - $@\n";
+ }
+ $exit = 1;
+};
+
+# Don't clear if nothing changed.
+if ($packages_modified) {
+ print <<'EOM';
+
+It is a good idea to clear the available list of old packages.
+However if you have only downloaded a Package files from non-main
+distributions you might not want to do this.
+
+EOM
+ if (yesno ('y', 'Do you want to clear available list')) {
+ print "Clearing...\n";
+ if (system('dpkg', '--clear-avail')) {
+ print 'dpkg --clear-avail failed.';
+ die 'error';
+ }
+ }
+}
+
+if (!$packages_modified) {
+ print "No Packages files was updated.\n";
+} else {
+ foreach my $file (@pkgfiles) {
+ if (system('dpkg', '--merge-avail', $file)) {
+ print "Dpkg merge available failed on $file";
+ $exit = 1;
+ }
+ }
+}
+exit $exit;
diff --git a/dselect/methods/media/README.media b/dselect/methods/media/README.media
new file mode 100644
index 0000000..468daa8
--- /dev/null
+++ b/dselect/methods/media/README.media
@@ -0,0 +1,101 @@
+Installation method for multiple binary media
+---------------------------------------------
+
+ This directory contains a method to be used within dselect in order to
+ access Debian binary packages stored across multiple binary media
+ (CDs, DVDs, BDs, or USBs).
+
+Acquiring package data
+---------------------
+
+ It is possible to access up to four binary directories within «dists/stable»:
+
+ . main
+ . contrib
+ . non-free
+ . local
+
+ The selected method will try to read the «Packages.cd» file from each
+ of these directories if it is available.
+
+Identifying the media
+----------------------
+
+ A unique name is associated to each media disc. This name should correspond
+ with the label on the front of the media disc. The name is also available on
+ the media disc, so the system can find out which media disc is inserted into
+ the computer at any time.
+
+Installing the files
+--------------------
+
+ At the beginning of the installation the “media” method will sort the list
+ of to-be-installed packages and install them media disc by media disc. If a
+ different media disc is required the user will be prompted to exchange
+ the media disc.
+
+Preparing multiple binary media discs
+-------------------------------------
+
+ Since the “media” method needs to know which packages are on which
+ media disc one cannot use regular «Packages» files. An additional data
+ field «X-Medium:» is required. The first media disc from the set should
+ contain all «Packages.cd» files. To be more convenient you should
+ include the «Packages.cd» files on all media discs. This ensures that
+ you do not have to start with the first media disc all the time.
+
+ Additionally the package needs to gain information which media disc is
+ currently used. Thus each media disc contains the file «.disk/info»
+ which contains the symbolic name for the media disc as specified by
+ «X-Medium:».
+
+ In order to be able to create the modified «Packages.cd» files, you
+ have to use the «-M medium» option of dpkg-scanpackages (supported
+ in dpkg-dev since 1.15.5).
+
+ To split the “main” distribution into two media discs you will need to
+ create a «Packages.cd» file for each «binary-$arch» directory.
+ Afterwards you simply append the second one to the first one and
+ put the resulting «Packages.cd» file into both «binary-$arch»
+ directories.
+
+Sample Layout
+-------------
+
+ Media disc 1 .disk/info = "Debian GNU/Linux binary-amd64"
+ dists/stable/main/binary-all/
+ binary-amd64/Packages.cd.gz
+ binary-amd64/net/foo.deb
+ contrib/binary-amd64/Packages.cd.gz
+ non-free/binary-amd64/Packages.cd.gz
+
+ Media disc 2 .disk/info = "Debian GNU/Linux contrib-amd64"
+ dists/stable/main/binary-amd64/Packages.cd.gz
+ contrib/binary-all/
+ binary-amd64/Packages.cd.gz
+ binary-amd64/net/foo.deb
+ non-free/binary-amd64/Packages.cd.gz
+
+ Media disc 3 .disk/info = "Debian GNU/Linux non-free-amd64"
+ dists/stable/main/binary-amd64/Packages.cd.gz
+ contrib/binary-amd64/Packages.cd.gz
+ non-free/binary-all/
+ binary-amd64/Packages.cd.gz
+ binary-amd64/net/foo.deb
+
+ To re-generate the Packages file you have to change directory into
+ «dists/stable/$part» and issue «dpkg-scanpackages» as follows. It is
+ assumed that you use regular compressed overrides files in
+ «/pub/debian/indices».
+
+ Media disc 1: dpkg-scanpackages -M "Debian GNU/Linux binary-amd64" \
+ binary-amd64 /pub/debian/indices/override.buster.gz \
+ dists/stable/ > binary-amd64/Packages
+
+ Media disc 2: dpkg-scanpackages -M "Debian GNU/Linux contrib-amd64" \
+ binary-amd64 /pub/debian/indices/override.buster.contrib.gz \
+ dists/stable/ > binary-amd64/Packages
+
+ Media disc 3: dpkg-scanpackages -M "Debian GNU/Linux non-free-amd64" \
+ binary-amd64 /pub/debian/indices/override.buster.non-free.gz \
+ dists/stable/ > binary-amd64/Packages
diff --git a/dselect/methods/media/desc.media b/dselect/methods/media/desc.media
new file mode 100644
index 0000000..e76022e
--- /dev/null
+++ b/dselect/methods/media/desc.media
@@ -0,0 +1,3 @@
+Installation from a media set containing a Debian distribution. The
+media discs may be or not be mounted already and should contain a standard
+ISO9660 media filesystem.
diff --git a/dselect/methods/media/install.sh b/dselect/methods/media/install.sh
new file mode 100755
index 0000000..625ca22
--- /dev/null
+++ b/dselect/methods/media/install.sh
@@ -0,0 +1,285 @@
+#!/bin/sh
+#
+# Copyright © 1995-1998 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright © 1998 Heiko Schlittermann <hs@schlittermann.de>
+#
+# This 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, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+cd "$vardir/methods/$method"
+
+. ./shvar.$option
+
+#debug() { echo "DEBUG: $@"; }
+debug() {
+ true
+}
+iarch=$(dpkg --print-architecture)
+ismulti() {
+ test -e "$1/.disk/info" || test -e "$1$2/.disk/info"
+}
+
+# 1/ mountpoint
+# 2/ hierarchy
+getdisklabel () {
+ debug "$1" "$2"
+ if [ -f $1/.disk/info ]; then
+ echo -n $(head -1 "$1/.disk/info")
+ elif [ -f $1$2/.disk/info ]; then
+ echo -n $(head -1 "$1$2/.disk/info")
+ else
+ echo -n 'Non-Debian disc'
+ fi
+}
+
+xit=1
+
+do_umount() {
+ if [ -n "$umount" ]; then
+ echo umount "$umount"
+ #">/dev/null" "2>&1"
+ fi
+}
+
+do_mount() {
+ if [ ! -b "$p_blockdev" ]; then
+ loop=",loop"
+ fi
+
+ if [ -n "$p_blockdev" ]; then
+ umount="$p_mountpoint"
+ echo mount -rt iso9660 -o nosuid,nodev${loop} "$p_blockdev" "$p_mountpoint"\; umount="$p_mountpoint"
+ fi
+}
+
+trap 'eval $(do_umount); exit $xit' 0
+
+eval $(do_mount)
+
+predep="$vardir/predep-package"
+while true; do
+ thisdisk="$(getdisklabel ${p_mountpoint} ${p_hierbase})"
+ set +e
+ dpkg --predep-package >"$predep"
+ rc=$?
+ set -e
+ if test $rc = 1; then
+ break
+ fi
+ test $rc = 0
+
+ perl -e '
+ ($binaryprefix,$predep,$thisdisk) = @ARGV;
+ open(P, "< $predep") or die "cannot open $predep: $!\n";
+ while (<P>) {
+ s/\s*\n$//;
+ $package = $_ if s/^Package: //i;
+ /^X-Medium:\s+(.*)\s*/ and $medium = $1;
+ @filename = split(/ /,$_) if s/^Filename: //i;
+ @msdosfilename = split(/ /,$_) if s/^MSDOS-Filename: //i;
+ }
+ die "internal error - no package" if length($package) == 0;
+ die "internal error - no filename" if not @filename;
+ die "internal error - mismatch >@filename< >@msdosfilename<"
+ if @filename && @msdosfilename &&
+ @filename != @msdosfilename;
+ if ($medium && ($medium ne $thisdisk)) {
+ print "
+
+This is
+ $thisdisk
+However, $package is expected on disc:
+ $medium
+Please change the discs and press <RETURN>.
+
+";
+ exit(1);
+ }
+ @invoke = (); $| =1;
+ for ($i = 0; $i <= $#filename; $i++) {
+ $ppart = $i+1;
+ print "Looking for part $ppart of $package ... ";
+ if (-f "$binaryprefix$filename[$i]") {
+ $print = $filename[$i];
+ $invoke = "$binaryprefix$filename[$i]";
+ } elsif (-f "$binaryprefix$msdosfilename[$i]") {
+ $print = $msdosfilename[$i];
+ $invoke = "$binaryprefix$msdosfilename[$i]";
+ } else {
+ $base = $filename[$i]; $base =~ s,.*/,,;
+ $msdosbase = $msdosfilename[$i]; $msdosbase =~ s,.*/,,;
+ $c = open(X, "-|"));
+ if (not defined $c) {
+ die "failed to fork for find: $!\n";
+ }
+ if (!$c) {
+ exec("find", "-L",
+ length($binaryprefix) ? $binaryprefix : ".",
+ "-name",$base,"-o","-name",$msdosbase);
+ die "failed to exec find: $!\n";
+ }
+ while (chop($invoke = <X>)) { last if -f $invoke; }
+ $print = $invoke;
+ if (substr($print,0,length($binaryprefix)+1) eq
+ "$binaryprefix/") {
+ $print = substr($print,length($binaryprefix));
+ }
+ }
+ if (!length($invoke)) {
+ warn "
+
+Cannot find the appropriate file(s) anywhere needed to install or upgrade
+package $package. Expecting version $version or later, as listed in the
+Packages file.
+
+Perhaps the package was downloaded with an unexpected name? In any case,
+you must find the file(s) and then either place it with the correct
+filename(s) (as listed in the Packages file or in $vardir/available)
+and rerun the installation, or upgrade the package by using
+\"dpkg --install --auto-deconfigure" by hand.
+
+";
+ exit(1);
+ }
+ print "$print\n";
+ push(@invoke,$invoke);
+ }
+ print "Running dpkg -iB for $package ...\n";
+ exec("dpkg","-iB","--",@invoke);
+ die "failed to exec dpkg: $!\n";
+ ' -- "$p_mountpoint$p_hierbase" "$predep" "$thisdisk"
+done
+
+perl -e '
+ $SIG{INT} = sub { cd $vardir; unlink <tmp/*>; exit 1; };
+ $| = 1;
+ my ($vardir, $mountpoint, $hierbase, $mount, $umount) = @ARGV;
+ my $line;
+ my $AVAIL = "$vardir/methods/media/available";
+ my $STATUS = "$vardir/status";
+ my %Installed, %Filename, %Medium;
+ print "Get currently installed package versions...";
+ open(IN, "$STATUS") or die "cannot open $STATUS: $!\n";
+ $line = 0;
+ { local $/ = "";
+ while (<IN>) {
+ my %status;
+ my @pstat;
+ $line++ % 20 or print ".";
+ s/\n\s+/ /g;
+ %status = ("", split /^(\S*?):\s*/m, $_);
+ map { chomp $status{$_}; $status{$_} =~ s/^\s*(.*?)\s*$/$1/;} keys %status;
+ @pstat = split(/ /, $status{Status});
+ next unless ($pstat[0] eq "install");
+ if ($pstat[2] eq "config-files" || $pstat[2] eq "not-installed") {
+ $Installed{$status{Package}} = "0.0";
+ } else {
+ $Installed{$status{Package}} = $status{Version} || "" ;
+ }
+ }; }
+ print "\nGot ", scalar keys %Installed, " installed/pending packages\n";
+ print "Scanning available packages...";
+ $line = 0;
+ open(IN, "$AVAIL") or die("Cannot open $AVAIL: $!\n");
+ { local $/ = "";
+ while (<IN>) {
+ my $updated;
+ $line++ % 20 or print ".";
+
+ s/\n\s+/ /g;
+ %avail = ("", split /^(\S*?):\s*/m, $_);
+ map { chomp $avail{$_}; $avail{$_} =~ s/^\s*(.*?)\s*$/$1/;} keys %avail;
+
+ next unless defined $Installed{$avail{Package}};
+
+ system "dpkg", "--compare-versions", $avail{Version}, "gt", $Installed{$avail{Package}};
+ $updated = ($? == 0);
+ #print "$avail{Package}(" . ($updated ? "+" : "=") . ") ";
+ $updated or next;
+
+ $Filename{$avail{Package}} = $avail{Filename};
+
+ next unless defined $avail{"X-Medium"};
+ ${Medium{$avail{"X-Medium"}}} or ${Medium{$avail{"X-Medium"}}} = [];
+ push @{${Medium{$avail{"X-Medium"}}}}, $avail{Package};
+ }; };
+ print "\n";
+
+ if (@_ = keys(%Medium)) {
+ print "You will need the following distribution disc(s):\n",
+ join (", ", @_), "\n";
+ }
+
+ foreach $need (sort @_) {
+ if (-r "$mountpoint/.disk/info") {
+ open(IN, "$mountpoint/.disk/info") or die("$mountpoint/.disk/info: $!\n");
+ } else {
+ open(IN, "$mountpoint/$hierbase/.disk/info") or die("$mountpoint/$hierbase/.disk/info: $!\n");
+ }
+ $disk = <IN>; chomp $disk; close(IN);
+
+ print "Processing disc\n $need\n";
+
+ while ($disk ne $need) {
+ print "Wrong disc. This is disc\n $disk\n";
+ print "However, the needed disc is\n $need\n";
+ print "Please change the discs and press <RETURN>\n";
+ system($umount);
+ <STDIN>;
+ system($mount);
+ $? and warn("cannot mount $mount\n");
+ } continue {
+ if (-r "$mountpoint/.disk/info") {
+ open(IN, "$mountpoint/.disk/info") or die("$mountpoint/.disk/info: $!\n");
+ } else {
+ open(IN, "$mountpoint/$hierbase/.disk/info") or die("$mountpoint/$hierbase/.disk/info: $!\n");
+ }
+ $disk = <IN>; chomp $disk; close(IN);
+ }
+
+ -d "tmp" || mkdir "tmp", 0755 or die("Cannot mkdir tmp: $!\n");
+ unlink <tmp/*>;
+
+ print "creating symlinks...\n";
+ foreach (@{$Medium{$need}}) {
+ ($basename = $Filename{$_}) =~ s/.*\///;
+ symlink "$mountpoint/$hierbase/$Filename{$_}",
+ "tmp/$basename";
+ }
+ chdir "tmp" or die "cannot chdir to tmp: $!\n";
+ system "dpkg", "-iGROEB", ".";
+ unlink <*>;
+ chdir "..";
+
+ if ($?) {
+ print "\nThe dpkg run produced errors. Please state whether to\n",
+ "continue with the next media disc. [Y/n]: ";
+ $answer = <STDIN>;
+ exit 1 if $answer =~ /^n/i;
+ $ouch = $?;
+ }
+ }
+
+ exit $ouch;
+
+' "$vardir" "$p_mountpoint" "$p_hierbase" "$(do_mount)" "$(do_umount)"
+
+echo -n 'Installation OK. Hit RETURN. '
+read response
+
+xit=0
diff --git a/dselect/methods/media/names b/dselect/methods/media/names
new file mode 100644
index 0000000..1d8879d
--- /dev/null
+++ b/dselect/methods/media/names
@@ -0,0 +1 @@
+31 media Install from a media set (CDs, DVDs, BDs, USBs).
diff --git a/dselect/methods/media/setup.sh b/dselect/methods/media/setup.sh
new file mode 100755
index 0000000..aad55a1
--- /dev/null
+++ b/dselect/methods/media/setup.sh
@@ -0,0 +1,485 @@
+#!/bin/sh
+#
+# Copyright © 1995-1998 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright © 1998 Heiko Schlittermann <hs@schlittermann.de>
+# Copyright © 1998-1999 Martin Schulze <joey@infodrom.north.de>
+#
+# This 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, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+
+test -d "$vardir/methods/$method" || mkdir "$vardir/methods/$method"
+cd "$vardir/methods/$method"
+tp="$(mktemp --tmpdir $method.XXXXXXXXXX)"
+
+iarch=$(dpkg --print-architecture)
+dist=stable
+
+xit=1
+trap '
+ rm -f $tp.?
+ if [ -n "$umount" ]; then
+ umount "$umount" >/dev/null 2>&1
+ fi
+ exit $xit
+' 0
+
+if ls -d "$tp.?" >/dev/null 2>&1; then
+ rm $tp.?
+fi
+
+#debug() { echo "DEBUG: $@"; }
+debug() {
+ true
+}
+ismulti() {
+ debug $1 $2; test -e "$1/.disk/info" || test -e "$1$2/.disk/info"
+}
+
+# 1/ mountpoint
+# 2/ hierarchy
+getdisklabel () {
+ debug "$1" "$2"
+ if [ -f $1/.disk/info ]; then
+ echo -n $(head -1 "$1/.disk/info")
+ elif [ -f $1$2/.disk/info ]; then
+ echo -n $(head -1 "$1$2/.disk/info")
+ else
+ echo -n 'Non-Debian disc'
+ fi
+}
+
+yesno () {
+ while true; do
+ echo -n "$2 [$1] "
+ read response
+ if [ -z "$response" ]; then
+ response="$1"
+ fi
+ case "$response" in
+ [Nn]*)
+ yesno=no
+ return
+ ;;
+ [Yy]*)
+ yesno=yes
+ return
+ ;;
+ esac
+ done
+}
+
+getblockdev () {
+ mountpoint="$vardir/methods/mnt"
+ if [ -z "$defaultdevice" ]; then
+ defaultdevice="$newdefaultdevice"
+ elif [ "$defaultdevice" != "$newdefaultdevice" ]; then
+ echo "Last time you specified installation from $defaultdevice."
+ fi
+ promptstring="$1"
+ while [ -z "$blockdevice" ]; do
+ echo -n "$promptstring [$defaultdevice]: "
+ read response
+ if [ -z "$response" ]; then
+ response="$defaultdevice"
+ fi
+ if [ ! -b "$response" ]; then
+ echo "$response is not a block device - will try as loopback."
+ loop=",loop"
+ fi
+ tryblockdevice="$response"
+ fstype=iso9660
+ umount="$mountpoint"
+ if mount -rt "$fstype" -o nosuid,nodev$loop "$tryblockdevice" "$mountpoint"
+ then
+ echo
+ blockdevice="$tryblockdevice"
+ else
+ umount=""
+ echo "Unable to mount $tryblockdevice on $mountpoint, type $fstype."
+ fi
+ done
+}
+
+outputparam () {
+ echo "$2" | sed -e "s/'/'\\\\''/; s/^/$1='/; s/$/'/" >&3
+}
+
+## MAIN
+intrkey="$(stty -a | sed -n 's/.*intr = \([^;]*\);.*/\1/p')"
+echo "
+If you make a mistake, use the interrupt key ($intrkey) to abort.
+"
+
+# State variables, “best first”
+# {main,ctb,nf,lcl}_{packages,binary}
+# Empty before we've found them or if they're not available,
+# set to the relevant bit under mountpoint otherwise.
+# hierbase
+# A directory containing a Debian FTP site mirror tree.
+# mountpoint
+# The mountpoint for the filesystem containing the stuff
+# empty or unset if we don't know yet, or if we haven't mounted anything;
+# may also be empty if ‘directory’ was set.
+# blockdevice
+# The actual block device to mount.
+# fstype
+# The filesystem type to use.
+# defaultdevice
+# The default block device to mount.
+
+p_usedevel=no
+if [ -f shvar.$option ]; then
+ . ./shvar.$option
+ defaultdevice="$p_blockdev"
+ usedevel="$p_usedevel"
+fi
+
+mount >$tp.m
+sed -n 's/ ([^)]*)$//; s/^[^ ]* on //; s/ type iso9660$//p' <$tp.m >$tp.l
+ncdroms=$(wc -l <$tp.l)
+if [ $ncdroms -gt 1 ]; then
+ response=""
+ while [ -z "$response" ]; do
+ echo 'Several media discs (ISO9660 filesystems) are mounted:'
+ grep -E 'type iso9660 \([^)]*\)$' <$tp.m | nl
+ echo -n "Is it any of these ? Type a number, or 'n' for none. "
+ read response
+ response="$(echo "$response" | sed -e 's/[ ]*$//')"
+ if expr "$response" : '[0-9][0-9]*$' >/dev/null && \
+ [ $response -ge 1 -a $response -le $ncdroms ]; then
+ mountpoint="$(sed -n $response'p' <$tp.l)"
+ echo
+ elif expr "$response" : '[Nn]' >/dev/null; then
+ mountpoint=""
+ else
+ response=""
+ fi
+ done
+elif [ $ncdroms = 1 ]; then
+ mountpoint="$(cat $tp.l)"
+ perl -ne 'print if s/ type iso9660 \([^)]*\)$// && s/ on .*$//;' \
+ <$tp.m >$tp.d
+ blockdevice="$(cat $tp.d)"
+ yesno yes \
+ "Found a media disc: $blockdevice, mounted on $mountpoint. Is it the right one?"
+ if [ $yesno = no ]; then
+ echo 'Unmounting it ...'
+ umount="$mountpoint"
+ while true; do
+ echo -n 'Please insert the right disc, and hit return: '
+ read response
+ if mount -rt iso9660 -o nosuid,nodev \
+ "$blockdevice" "$mountpoint"; then
+ echo
+ break
+ fi
+ done
+ fi
+fi
+if [ -z "$mountpoint" ]; then
+ if [ -b /dev/cdrom ]; then
+ echo 'Found that /dev/cdrom exists and is a block device.'
+ newdefaultdevice=/dev/cdrom
+ fi
+ getblockdev 'Insert the media and enter the block device name'
+fi
+
+if [ -n "$mountpoint" ]; then
+ # We must have $mountpoint
+ echo \
+'All directory names should be entered relative to the root of the media disc.
+'
+fi
+
+# now try to get the users idea where the debian
+# hierarchy start below the mointpoint
+
+debug "mountpoint: $mountpoint"
+while true; do
+ if ismulti "${mountpoint}" "${hierbase}"; then
+ multi=yes
+ fi
+
+ echo \
+"Need to know where on the media disc the top level of the Debian
+distribution is - this will usually contain the 'dists' directory.
+
+If the media disc is badly organized and doesn't have a straightforward copy of
+the distribution you may answer 'none' and the needed parts will be prompted
+individually."
+
+ defhierbase=none
+ if [ -n "$p_hierbase" ]; then
+ if [ -d "$mountpoint/$p_hierbase/dists/$dist/main/binary-$iarch" \
+ -o -n "$multi" ]; then
+ echo "Last time you said '$p_hierbase', and that looks plausible."
+ defhierbase="$p_hierbase"
+ else
+ echo "
+Last time you said '$p_hierbase', but that doesn't look plausible,
+since '$p_hierbase/dists/$dist/main/binary-$iarch' doesn't seem to exist.
+And it does not appear that you are using a multiple media set."
+ fi
+ fi
+
+ # at this point defhierbase is set if it looks plausible
+ # if ‘none’ was entered, we assume a media with a debian/ directory
+
+ if [ none = "$defhierbase" -a -d "$mountpoint/debian/dists/$dist/main/binary-$iarch" ]
+ then
+ echo "'/debian' exists and looks plausible, so that's the default."
+ defhierbase=/debian
+ fi
+
+ echo -n "Distribution top level ? [$defhierbase] "
+ read response
+ if [ -z "$response" ]; then
+ response="$defhierbase"
+ fi
+ if [ none = "$response" ]; then
+ hierbase=""
+ break
+ elif ismulti "$mountpoint" "$response" && [ -z "$multi" ]; then
+ multi=yes
+ fi
+
+ if ! [ -d "$mountpoint/$response/dists/$dist/main/binary-$iarch" \
+ -o -n "$multi" ]; then
+ echo \
+"Neither $response/dists/$dist/main/binary-$iarch does not exist,
+nor are you using a multiple media set"
+ break
+ fi
+
+ hierbase="$(echo "$response" | sed -e 's:/$::; s:^/*:/:; s:/\+:/:g;')"
+ debug "hierbase: [$hierbase]"
+
+ if [ -n "$multi" ]; then
+ disklabel=$(getdisklabel "$mountpoint" "/$response")
+ echo "Ok, this is disc"
+ echo " $disklabel"
+ #echo "Updating multiple media contents file cache ..."
+ #multi_contentsfile="${mountpoint}/${response}/.disk/contents.gz"
+ #zcat "$multi_contentsfile" > disk-contents.$option
+ fi
+
+ break;
+done
+
+distribution=$dist
+if [ -n "$hierbase" ]; then
+ if [ -d "$mountpoint/$hierbase/dists/unstable/binary-$iarch" ]; then
+ echo \
+'
+Both a stable released distribution and a work-in-progress
+development tree are available for installation. Would you like to
+use the unreleased development tree (this is only recommended for
+experts who like to live dangerously and want to help with testing) ?'
+ yesno "$p_usedevel" 'Use unreleased development distribution ?'
+ usedevel="$yesno"
+ if [ "$usedevel" = yes ]; then
+ distribution=development
+ fi
+ else
+ usedevel=no
+ fi
+ echo
+fi
+
+case "$hierbase" in
+/* )
+ ;;
+'' )
+ ;;
+* )
+ hierbase="/$hierbase"
+ ;;
+esac
+
+check_binary () {
+ # args: area-in-messages directory
+ debug "check_binary($@)"
+
+ if [ ! -d "${mountpoint}$2" -a -z "$multi" ]; then
+ echo "'$2' does not exist."
+ return
+ fi
+
+# In this special case it is ok for a sub-distribution to not contain any
+# .deb files. Each media should contain all Packages.cd files but does not
+# need to contain the .deb files.
+#
+# if ! { find -L "$mountpoint$2" -name '*.deb' -print \
+# | head -1 | grep . ; } >/dev/null 2>&1 && [ -z "$multi" ];
+# then
+# echo "'$2' does not contain any *.deb packages."
+# return
+# fi
+
+ this_binary="$2"
+ echo -n "Using '$this_binary' as $1 binary directory"
+
+ if [ -n "$multi" ]; then
+ this_disk=$(getdisklabel ${mountpoint} "/$hierbase")
+ echo " from disc"
+ echo " '$this_disk'"
+ else
+ echo ""
+ fi
+}
+
+find_area () {
+ # args: area-in-messages area-in-vars subdirectory-in-hier
+ # last-time-binary last-time-packages
+ debug "find_area($@)"
+ this_binary=''
+ this_packages=''
+ this_disk=''
+ if [ -n "$hierbase" ]; then
+ check_binary $1 $(echo "$hierbase/dists/$3/$1/binary-$iarch" | sed 's:/\+:/:g')
+ debug "THIS_BINARY $this_binary"
+ fi
+ if [ $2 = nf -a -z "$this_binary" ]; then
+ echo "
+Note: most media distributions of Debian do not include programs available
+in the 'non-free' directory of the distribution site.
+This is because these programs are under licenses that do not allow source
+modification or prevent distribution for profit on a media, or other
+restrictions that make them not free software.
+If you wish to install these programs you will have to get them from an
+alternative source."
+ fi
+ while [ -z "$this_binary" ]; do
+ defaultbinary="$4"
+ echo "
+Which directory contains the *.deb packages from the $1 distribution
+area (this directory is named '$3/binary' on the distribution site) ?
+Say 'none' if this area is not available."
+ if [ $2 != main -a -z "$defaultbinary" ]; then
+ defaultbinary=none
+ fi
+ echo -n \
+"Enter _$1_ binary directory. [$4]
+ ? "
+ read response
+ if [ -z "$response" -a -n "$defaultbinary" ]; then
+ response="$defaultbinary"
+ fi
+ if [ none = "$response" ]; then
+ break
+ fi
+ case "$response" in
+ '' | none)
+ continue
+ ;;
+ esac
+ check_binary $1 "$(echo "$response" | sed -e 's:/$::; s:^/*:/:')"
+ done
+ if [ -n "$this_binary" ]; then
+ if [ "$multi" = "yes" ]; then
+ for f in Packages.cd.gz packages.cd.gz Packages.cd packages.cd; do
+ if [ -f "$mountpoint/$this_binary/$f" ]; then
+ this_packages="$this_binary/$f"
+ echo "Using '$this_packages' for $1."
+ break
+ fi
+ done
+ elif [ -f "${mountpoint}${hierbase}/.disk/packages/$1/Packages.gz" ]; then
+ this_packages=$(echo "${hierbase}/.disk/packages/$1/Packages.gz"|sed 's:/\+:/:g')
+ echo "Using '${this_packages}' for $1."
+ fi
+ while [ -z "$this_packages" ]; do
+ echo -n "
+Cannot find the $1 'Packages.cd' file. The information in the
+'Packages.cd' file is important for package selection during new
+installations, and is very useful for upgrades.
+
+If you overlooked it when downloading you should do get it now and
+return to this installation procedure when you have done so: you will
+find one Packages.cd file and one Packages.cd.gz file -- either will do --
+in the 'binary' subdirectory of each area on the FTP sites and
+media discs. Alternatively (and this will be rather slow) the packages in
+the distribution area can be scanned - say 'scan' if you want to do so.
+
+You need a separate Packages.cd file from each of the distribution areas
+you wish to install.
+
+Where is the _$1_ 'Packages.cd' file (if none is available, say 'none')
+[$5]
+ ? "
+ read response
+ if [ -z "$response" -a -n "$5" ]; then
+ response="$5"
+ fi
+ case "$response" in
+ '')
+ break
+ ;;
+ none)
+ break
+ ;;
+ scan)
+ this_packages=scan
+ ;;
+ /*)
+ this_packages="$response"
+ ;;
+ *)
+ this_packages="/$response"
+ ;;
+ esac
+ done
+ fi
+ eval $2'_binary="$this_binary"'
+ eval $2'_packages="$this_packages"'
+ eval $2'_disk="$this_disk"'
+}
+
+find_area main main "$distribution" "$p_main_binary" "$p_main_packages"
+find_area contrib ctb "$distribution" "$p_ctb_binary" "$p_ctb_packages"
+find_area non-free nf "$distribution" "$p_nf_binary" "$p_nf_packages"
+find_area local lcl local "$p_lcl_binary" "$p_lcl_packages"
+
+echo -n '
+Hit RETURN to continue. '
+read response
+
+exec 3>shvar.$option.new
+
+outputparam p_blockdev "$blockdevice"
+outputparam p_fstype "$fstype"
+outputparam p_mountpoint "$mountpoint"
+outputparam p_hierbase "$hierbase"
+outputparam p_usedevel "$usedevel"
+outputparam p_main_packages "$main_packages"
+outputparam p_main_binary "$main_binary"
+outputparam p_main_disk "$main_disk"
+outputparam p_ctb_packages "$ctb_packages"
+outputparam p_ctb_binary "$ctb_binary"
+outputparam p_ctb_disk "$ctb_disk"
+outputparam p_nf_packages "$nf_packages"
+outputparam p_nf_binary "$nf_binary"
+outputparam p_nf_disk "$nf_disk"
+outputparam p_lcl_packages "$lcl_packages"
+outputparam p_lcl_binary "$lcl_binary"
+outputparam p_multi "$multi"
+outputparam p_multi_contentsfile "$multi_contentsfile"
+
+mv shvar.$option.new shvar.$option
+
+xit=0
diff --git a/dselect/methods/media/update.sh b/dselect/methods/media/update.sh
new file mode 100755
index 0000000..5045332
--- /dev/null
+++ b/dselect/methods/media/update.sh
@@ -0,0 +1,125 @@
+#!/bin/sh
+#
+# Copyright © 1995-1998 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright © 1998 Heiko Schlittermann <hs@schlittermann.de>
+#
+# This 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, see <https://www.gnu.org/licenses/>.
+
+set -e
+vardir="$1"
+method=$2
+option=$3
+iarch=$(dpkg --print-architecture)
+
+cd "$vardir/methods/$method"
+
+. ./shvar.$option
+
+#debug() { echo "DEBUG: $@"; }
+debug() {
+ true
+}
+ismulti() {
+ debug $1 $2
+ test -e "$1/.disk/info" || test -e "$1$2/.disk/info"
+}
+
+packages=0
+for f in main ctb nf lcl; do
+ eval 'this_packages=$p_'$f'_packages'
+
+ if [ -n "$this_packages" ]; then
+ packages=1
+ fi
+done
+
+if [ $packages eq 0 ]; then
+ echo '
+No Packages files available, cannot update available packages list.
+Hit RETURN to continue. '
+ read response
+ exit 0
+fi
+
+xit=1
+trap '
+ for area in main ctb nf lcl; do
+ rm -f packages-$area
+ done
+ if [ -n "$umount" ]; then
+ umount "$umount" >/dev/null 2>&1
+ fi
+ exit $xit
+' 0
+
+if [ ! -b "$p_blockdev" ]; then
+ loop=",loop"
+fi
+
+if [ -n "$p_blockdev" ]; then
+ umount="$p_mountpoint"
+ mount -rt "$p_fstype" -o nosuid,nodev${loop} "$p_blockdev" "$p_mountpoint"
+fi
+
+updatetype=update
+
+if [ -z "$p_multi" ]; then
+ exit 1
+fi
+
+for f in main ctb nf lcl; do
+ eval 'this_packages=$p_'$f'_packages'
+ case "$this_packages" in
+ '')
+ continue
+ ;;
+ scan)
+ eval 'this_binary=$p_'$f'_binary'
+ if [ -z "$this_binary" ]; then
+ continue
+ fi
+ if [ "$updatetype" = update ]; then
+ dpkg --clear-avail
+ updatetype=merge
+ fi
+ echo Running dpkg --record-avail -R "$p_mountpoint$this_binary"
+ dpkg --record-avail -R "$p_mountpoint$this_binary"
+ ;;
+ *)
+ packagesfile="$p_mountpoint$this_packages"
+ case "$packagesfile" in
+ *.gz | *.Z | *.GZ | *.z)
+ echo -n "Uncompressing $packagesfile ... "
+ zcat <"$packagesfile" >packages-$f
+ echo done.
+ dpkg --$updatetype-avail packages-$f
+ updatetype=merge
+ ;;
+ '')
+ ;;
+ *)
+ dpkg --$updatetype-avail "$packagesfile"
+ updatetype=merge
+ ;;
+ esac
+ ;;
+ esac
+done
+
+cp -f $vardir/available $vardir/methods/$method
+
+echo -n 'Update OK. Hit RETURN. '
+read response
+
+xit=0