summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/acquire.cc13
-rw-r--r--apt-pkg/packagemanager.cc106
-rw-r--r--apt-pkg/packagemanager.h3
-rw-r--r--cmdline/apt-config.cc119
-rw-r--r--cmdline/apt-get.cc12
-rw-r--r--cmdline/makefile8
-rw-r--r--doc/examples/apt.conf8
-rw-r--r--dselect/desc.apt5
-rwxr-xr-xdselect/install74
-rw-r--r--dselect/names1
-rwxr-xr-xdselect/setup286
-rwxr-xr-xdselect/update22
12 files changed, 600 insertions, 57 deletions
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index 353e2f698..3bd7662fd 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: acquire.cc,v 1.16 1998/11/14 01:39:45 jgg Exp $
+// $Id: acquire.cc,v 1.17 1998/11/22 23:37:03 jgg Exp $
/* ######################################################################
Acquire - File Acquiration
@@ -459,11 +459,14 @@ pkgAcquire::Queue::~Queue()
/* */
void pkgAcquire::Queue::Enqueue(ItemDesc &Item)
{
+ QItem **I = &Items;
+ for (; *I != 0; I = &(*I)->Next);
+
// Create a new item
- QItem *I = new QItem;
- I->Next = Items;
- Items = I;
- *I = Item;
+ QItem *Itm = new QItem;
+ *Itm = Item;
+ Itm->Next = 0;
+ *I = Itm;
Item.Owner->QueueCounter++;
if (Items->Next == 0)
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index e6222f003..7dd6b8a27 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: packagemanager.cc,v 1.6 1998/11/22 03:20:33 jgg Exp $
+// $Id: packagemanager.cc,v 1.7 1998/11/22 23:37:05 jgg Exp $
/* ######################################################################
Package Manager - Abstacts the package manager
@@ -51,18 +51,24 @@ pkgPackageManager::~pkgPackageManager()
bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
pkgRecords *Recs)
{
- pkgCache::PkgIterator I = Cache.PkgBegin();
- for (;I.end() != true; I++)
- {
- // Not interesting
- if ((Cache[I].InstallVer == (pkgCache::Version *)I.CurrentVer() &&
- I.State() != pkgCache::PkgIterator::NeedsUnpack) ||
- Cache[I].Delete() == true)
+ if (CreateOrderList() == false)
+ return false;
+
+ if (List->OrderUnpack() == false)
+ return _error->Error("Internal ordering error");
+
+ for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
+ {
+ PkgIterator Pkg(Cache,*I);
+
+ // Skip packages to erase
+ if (Cache[Pkg].Delete() == true)
continue;
- new pkgAcqArchive(Owner,Sources,Recs,Cache[I].InstVerIter(Cache),
- FileNames[I->ID]);
+ new pkgAcqArchive(Owner,Sources,Recs,Cache[Pkg].InstVerIter(Cache),
+ FileNames[Pkg->ID]);
}
+
return true;
}
/*}}}*/
@@ -88,6 +94,50 @@ bool pkgPackageManager::FixMissing()
}
/*}}}*/
+// PM::CreateOrderList - Create the ordering class /*{{{*/
+// ---------------------------------------------------------------------
+/* This populates the ordering list with all the packages that are
+ going to change. */
+bool pkgPackageManager::CreateOrderList()
+{
+ delete List;
+ List = new pkgOrderList(Cache);
+
+ // Generate the list of affected packages and sort it
+ for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+ {
+ // Consider all depends
+ if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+ {
+ List->Flag(I,pkgOrderList::Immediate);
+ if (Cache[I].InstallVer != 0)
+ for (DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
+ D.end() == false; D++)
+ if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
+ List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+ if (I->CurrentVer != 0)
+ for (DepIterator D = I.CurrentVer().DependsList();
+ D.end() == false; D++)
+ if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
+ List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
+ }
+
+ // Not interesting
+ if ((Cache[I].Keep() == true ||
+ Cache[I].InstVerIter(Cache) == I.CurrentVer()) &&
+ I.State() == pkgCache::PkgIterator::NeedsNothing)
+ continue;
+
+ // Append it to the list
+ List->push_back(I);
+
+ if ((I->Flags & pkgCache::Flag::ImmediateConf) == pkgCache::Flag::ImmediateConf)
+ List->Flag(I,pkgOrderList::Immediate);
+ }
+
+ return true;
+}
+ /*}}}*/
// PM::DepAlwaysTrue - Returns true if this dep is irrelevent /*{{{*/
// ---------------------------------------------------------------------
/* The restriction on provides is to eliminate the case when provides
@@ -412,41 +462,9 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
/* */
bool pkgPackageManager::OrderInstall()
{
- delete List;
- List = new pkgOrderList(Cache);
+ if (CreateOrderList() == false)
+ return false;
- // Generate the list of affected packages and sort it
- for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
- {
- // Consider all depends
- if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
- {
- List->Flag(I,pkgOrderList::Immediate);
- if (Cache[I].InstallVer != 0)
- for (DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
- D.end() == false; D++)
- if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
- List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
- if (I->CurrentVer != 0)
- for (DepIterator D = I.CurrentVer().DependsList();
- D.end() == false; D++)
- if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
- List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
- }
-
- // Not interesting
- if ((Cache[I].Keep() == true ||
- Cache[I].InstVerIter(Cache) == I.CurrentVer()) &&
- I.State() == pkgCache::PkgIterator::NeedsNothing)
- continue;
-
- // Append it to the list
- List->push_back(I);
-
- if ((I->Flags & pkgCache::Flag::ImmediateConf) == pkgCache::Flag::ImmediateConf)
- List->Flag(I,pkgOrderList::Immediate);
- }
-
if (Debug == true)
clog << "Begining to order" << endl;
diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h
index e0e9dc108..5265c315c 100644
--- a/apt-pkg/packagemanager.h
+++ b/apt-pkg/packagemanager.h
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: packagemanager.h,v 1.6 1998/11/22 03:20:34 jgg Exp $
+// $Id: packagemanager.h,v 1.7 1998/11/22 23:37:06 jgg Exp $
/* ######################################################################
Package Manager - Abstacts the package manager
@@ -55,6 +55,7 @@ class pkgPackageManager
bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
bool OrderInstall();
bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver);
+ bool CreateOrderList();
// Analysis helpers
bool DepAlwaysTrue(DepIterator D);
diff --git a/cmdline/apt-config.cc b/cmdline/apt-config.cc
new file mode 100644
index 000000000..7dfb59192
--- /dev/null
+++ b/cmdline/apt-config.cc
@@ -0,0 +1,119 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt-config.cc,v 1.1 1998/11/22 23:37:07 jgg Exp $
+/* ######################################################################
+
+ APT Config - Program to manipulate APT configuration files
+
+ This program will parse a config file and then do something with it.
+
+ Commands:
+ shell - Shell mode. After this a series of word pairs should occure.
+ The first is the environment var to set and the second is
+ the key to set it from. Use like:
+ eval `apt-config shell QMode apt::QMode`
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include <apt-pkg/cmndline.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/init.h>
+#include "config.h"
+
+#include <iostream>
+ /*}}}*/
+
+// DoShell - Handle the shell command /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DoShell(CommandLine &CmdL)
+{
+ for (const char **I = CmdL.FileList + 1; *I != 0; I += 2)
+ {
+ if (I[1] == 0)
+ return _error->Error("Arguments not in pairs");
+ if (_config->Exists(I[1]) == true)
+ cout << *I << "=\"" << _config->Find(I[1]) << '"' << endl;
+ }
+
+ return true;
+}
+ /*}}}*/
+// ShowHelp - Show the help screen /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int ShowHelp()
+{
+ cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
+ " compiled on " << __DATE__ << " " << __TIME__ << endl;
+
+ cout << "Usage: apt-config [options] command" << endl;
+ cout << endl;
+ cout << "apt-config is a simple tool to read the APT config file" << endl;
+ cout << endl;
+ cout << "Commands:" << endl;
+ cout << " shell - Shell mode" << endl;
+ cout << endl;
+ cout << "Options:" << endl;
+ cout << " -h This help text." << endl;
+ cout << " -c=? Read this configuration file" << endl;
+ cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
+ return 100;
+}
+ /*}}}*/
+
+int main(int argc,const char *argv[])
+{
+ CommandLine::Args Args[] = {
+ {'h',"help","help",0},
+ {'c',"config-file",0,CommandLine::ConfigFile},
+ {'o',"option",0,CommandLine::ArbItem},
+ {0,0,0,0}};
+
+ // Parse the command line and initialize the package library
+ CommandLine CmdL(Args,_config);
+ if (pkgInitialize(*_config) == false ||
+ CmdL.Parse(argc,argv) == false)
+ {
+ _error->DumpErrors();
+ return 100;
+ }
+
+ // See if the help should be shown
+ if (_config->FindB("help") == true ||
+ CmdL.FileSize() == 0)
+ return ShowHelp();
+
+ // Match the operation
+ struct
+ {
+ const char *Match;
+ bool (*Handler)(CommandLine &);
+ } Map[] = {{"shell",&DoShell},
+ {0,0}};
+ int I;
+ for (I = 0; Map[I].Match != 0; I++)
+ {
+ if (strcmp(CmdL.FileList[0],Map[I].Match) == 0)
+ {
+ if (Map[I].Handler(CmdL) == false && _error->PendingError() == false)
+ _error->Error("Handler silently failed");
+ break;
+ }
+ }
+
+ // No matching name
+ if (Map[I].Match == 0)
+ _error->Error("Invalid operation %s", CmdL.FileList[0]);
+
+ // Print any errors or warnings found during parsing
+ if (_error->empty() == false)
+ {
+ bool Errors = _error->PendingError();
+ _error->DumpErrors();
+ return Errors == true?100:0;
+ }
+
+ return 0;
+}
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index e00cf53c3..279a0c4ed 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: apt-get.cc,v 1.15 1998/11/22 03:20:36 jgg Exp $
+// $Id: apt-get.cc,v 1.16 1998/11/22 23:37:07 jgg Exp $
/* ######################################################################
apt-get - Cover for dpkg
@@ -502,11 +502,13 @@ bool InstallPackages(pkgDepCache &Cache,bool ShwKept,bool Ask = true)
if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
return false;
+ // Display statistics
unsigned long FetchBytes = Fetcher.FetchNeeded();
unsigned long DebBytes = Fetcher.TotalNeeded();
if (DebBytes != Cache.DebSize())
c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
+ // Number of bytes
c1out << "Need to get ";
if (DebBytes != FetchBytes)
c1out << SizeToStr(FetchBytes) << '/' << SizeToStr(DebBytes);
@@ -515,6 +517,7 @@ bool InstallPackages(pkgDepCache &Cache,bool ShwKept,bool Ask = true)
c1out << " of archives. After unpacking ";
+ // Size delta
if (Cache.UsrSize() >= 0)
c1out << SizeToStr(Cache.UsrSize()) << " will be used." << endl;
else
@@ -523,6 +526,7 @@ bool InstallPackages(pkgDepCache &Cache,bool ShwKept,bool Ask = true)
if (_error->PendingError() == true)
return false;
+ // Prompt to continue
if (Ask == true)
{
if (_config->FindI("quiet",0) < 2 ||
@@ -783,10 +787,7 @@ bool DoInstall(CommandLine &CmdL)
// See if we need to prompt
if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
- {
- cout << "Boink" << endl;
return InstallPackages(Cache,false,false);
- }
return InstallPackages(Cache,false);
}
@@ -867,6 +868,9 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
/* */
bool DoClean(CommandLine &CmdL)
{
+ pkgAcquire Fetcher;
+ Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
+ Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
return true;
}
/*}}}*/
diff --git a/cmdline/makefile b/cmdline/makefile
index d3c1012d9..e52328440 100644
--- a/cmdline/makefile
+++ b/cmdline/makefile
@@ -11,8 +11,14 @@ SLIBS = -lapt-pkg
SOURCE = apt-cache.cc
include $(PROGRAM_H)
-# The apt-config program
+# The apt-get program
PROGRAM=apt-get
SLIBS = -lapt-pkg
SOURCE = apt-get.cc acqprogress.cc
include $(PROGRAM_H)
+
+# The apt-config program
+PROGRAM=apt-config
+SLIBS = -lapt-pkg
+SOURCE = apt-config.cc
+include $(PROGRAM_H)
diff --git a/doc/examples/apt.conf b/doc/examples/apt.conf
index ddd7d512d..8bd47550a 100644
--- a/doc/examples/apt.conf
+++ b/doc/examples/apt.conf
@@ -1,4 +1,4 @@
-// $Id: apt.conf,v 1.12 1998/11/22 03:20:38 jgg Exp $
+// $Id: apt.conf,v 1.13 1998/11/22 23:37:09 jgg Exp $
/* This file is an index of all APT configuration directives. It should
NOT actually be used as a real config file, though it is a completely
valid file.
@@ -75,11 +75,15 @@ Dir
methods "/home/jgg/work/apt/build/bin/methods/";
gzip "/bin/gzip";
dpkg "/usr/bin/dpkg";
+ apt-get "/usr/bin/apt-get";
+ apt-cache "/usr/bin/apt-get";
};
};
DSelect {
-
+ Clean "auto";
+ Options "-f";
+ UpdateOptions "";
}
/* Options you can set to see some debugging text They corrispond to names
diff --git a/dselect/desc.apt b/dselect/desc.apt
new file mode 100644
index 000000000..ef6364e11
--- /dev/null
+++ b/dselect/desc.apt
@@ -0,0 +1,5 @@
+The APT installation method encompasses most other installation methods
+under the umbrella of the new Package Acquisition code. This method allows
+installation from locations in the filesystem, ftp and http URLs, supports
+full installation ordering and integrity checking as well as multiple
+sources. See the man pages apt-get(8) and source.list(5)
diff --git a/dselect/install b/dselect/install
new file mode 100755
index 000000000..7c4237458
--- /dev/null
+++ b/dselect/install
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+# Get the configuration from /etc/apt/apt.conf
+CLEAN="auto"
+OPTS="-f"
+APTGET="/usr/bin/apt-get"
+DPKG="/usr/bin/dpkg"
+sh -e
+RES=`apt-config shell CLEAN DSelect::Clean OPTS DSelect::Options \
+ DPKG Dir::Bin::dpkg APTGET Dir::Bin::apt-get`
+eval $RES
+sh +e
+
+# Yes/No Prompter
+function yesno() {
+# $1 = prompt
+# $2 = default(y)
+ local ans def defp
+ if [ "$2" ];then
+ case $2 in
+ Y|y) defp="(Y/n)" def=y;;
+ N|n) defp="(y/N)" def=n;;
+ *) echo "Bad default setting!" 1>&2; exit 1;;
+ esac
+ else
+ defp="(y/N)" def=n
+ fi
+ while :;do
+ echo -n "$1$defp" 1>&3
+ read ans
+ case $ans in
+ Y|y|N|n) break;;
+ "") ans=$def;break;;
+ esac
+ echo
+ done
+ echo $ans | tr YN yn
+}
+
+#$APTGET $OPTS dselect-upgrade
+RES=$?
+
+# 1 means the user choose no at the prompt
+if [ $RES -eq 1 ]; then
+ exit 0
+fi
+
+# Finished OK
+if [ $RES -eq 0 ]; then
+ # Check the cleaning mode
+ case `echo $CLEAN | tr '[:upper:]' '[:lower:]'` in
+ always|auto)
+ $APTGET clean && echo "Press enter to continue." && read RES && exit 0;
+ ;;
+ prompt)
+ exec 3>&1
+ if [ `yesno "Do you want to erase the downloaded files " y` = y ]; then
+ $APTGET clean && echo "Press enter to continue." && read RES && exit 0;
+ fi
+ ;;
+ *)
+ ;;
+ esac
+else
+ echo "Some errors occurred while unpacking. I'm going to configure the"
+ echo "packages that were installed. This may result in duplicate errors"
+ echo "or errors caused by missing dependencies. This is OK, only the errors"
+ echo "above this message are important. Please fix them and run [I]nstall again"
+ echo "Press enter to continue."
+ read RES && $DPKG --configure -a
+ exit 100
+fi
+
+exit $?
diff --git a/dselect/names b/dselect/names
new file mode 100644
index 000000000..8daa53782
--- /dev/null
+++ b/dselect/names
@@ -0,0 +1 @@
+70 apt APT Acquisition [file,http,ftp]
diff --git a/dselect/setup b/dselect/setup
new file mode 100755
index 000000000..fd0daa927
--- /dev/null
+++ b/dselect/setup
@@ -0,0 +1,286 @@
+#!/usr/bin/perl -w
+# -*- Mode: Perl -*-
+# setup.pl ---
+# Author : Manoj Srivastava ( srivasta@tiamat.datasync.com )
+# Created On : Wed Mar 4 15:11:47 1998
+# Created On Node : tiamat.datasync.com
+# Last Modified By : Manoj Srivastava
+# Last Modified On : Tue May 19 11:25:32 1998
+# Last Machine Used: tiamat.datasync.com
+# Update Count : 87
+# Status : Unknown, Use with caution!
+# HISTORY :
+# Description :
+# This file is designed to go into /usr/lib/apt/methods/setup
+#
+
+#use strict;
+#use diagnostics;
+#printf STDERR "DEBUG: Arguments $ARGV[0];$ARGV[1];$ARGV[2];\n";
+
+
+# Handle the arguments
+my $vardir=$ARGV[0];
+my $method=$ARGV[1];
+my $option=$ARGV[2];
+my $config_file = '/etc/apt/sources.list';
+
+my $boldon=`setterm -bold on`;
+my $boldoff=`setterm -bold off`;
+
+my @known_types = ('deb');
+my @known_access = ('http', 'ftp', 'file');
+my @typical_distributions = ('stable', 'unstable', 'frozen', 'non-US');
+my @typical_components = ('main', 'contrib', 'non-free');
+
+my %known_access = map {($_,$_)} @known_access;
+my %typical_distributions = map {($_,$_)} @typical_distributions;
+
+# Read the config file, creating source records
+sub read_config {
+ my %params = @_;
+ my @Config = ();
+
+ die "Required parameter Filename Missing" unless
+ $params{'Filename'};
+
+ open (CONFIG, "$params{'Filename'}") ||
+ die "Could not open $params{'Filename'}: $!";
+ while (<CONFIG>) {
+ chomp;
+ my $rec = {};
+ my ($type, $urn, $distribution, $components) =
+ m/^\s*(\S+)\s+(\S+)\s+(\S+)\s*(?:\s+(\S.*))?$/o;
+ $rec->{'Type'} = $type;
+ $rec->{'URN'} = $urn;
+ $rec->{'Distribution'} = $distribution;
+ $rec->{'Components'} = $components;
+ push @Config, $rec;
+ }
+ close(CONFIG);
+
+ return @Config;
+}
+
+# write the config file; writing out the current set of source records
+sub write_config {
+ my %params = @_;
+ my $rec;
+ my %Seen = ();
+
+ die "Required parameter Filename Missing" unless
+ $params{'Filename'};
+ die "Required parameter Config Missing" unless
+ $params{'Config'};
+
+ open (CONFIG, ">$params{'Filename'}") ||
+ die "Could not open $params{'Filename'} for writing: $!";
+ for $rec (@{$params{'Config'}}) {
+ my $line = "$rec->{'Type'} $rec->{'URN'} $rec->{'Distribution'} ";
+ $line .= "$rec->{'Components'}" if $rec->{'Components'};
+ $line .= "\n";
+ print CONFIG $line unless $Seen{$line}++;
+ }
+ close(CONFIG);
+}
+
+# write the config file; writing out the current set of source records
+sub print_config {
+ my %params = @_;
+ my $rec;
+ my %Seen = ();
+
+ die "Required parameter Config Missing" unless
+ $params{'Config'};
+
+ for $rec (@{$params{'Config'}}) {
+ next unless $rec;
+
+ my $line = "$rec->{'Type'} " if $rec->{'Type'};
+ $line .= "$rec->{'URN'} " if $rec->{'URN'};
+ $line .= "$rec->{'Distribution'} " if $rec->{'Distribution'};
+ $line .= "$rec->{'Components'}" if $rec->{'Components'};
+ $line .= "\n";
+ print $line unless $Seen{$line}++;
+ }
+}
+
+# Ask for and add a source record
+sub get_source {
+ my %params = @_;
+ my $rec = {};
+ my $answer;
+ my ($type, $urn, $distribution, $components);
+
+ if ($params{'Default'}) {
+ ($type, $urn, $distribution, $components) =
+ $params{'Default'} =~ m/^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S.*)$/o;
+ }
+
+ $type = 'deb';
+ $urn = "http://llug.sep.bnl.gov/debian" unless $urn;
+ $distribution = "stable" unless $distribution;
+ $components = "main contrib non-free" unless $components;
+
+
+ $rec->{'Type'} = 'deb';
+ $| = 1;
+
+ my $done = 0;
+
+ while (!$done) {
+ print "\n";
+ print "$boldon URL [$urn]: $boldoff";
+
+ $answer=<STDIN>;
+ chomp ($answer);
+ $answer =~ s/\s*//og;
+
+ if ($answer =~ /^\s*$/o) {
+ $rec->{'URN'} = $urn;
+ last;
+ }
+ else {
+ my ($scheme) = $answer =~ /^\s*([^:]+):/o;
+ if (! defined $known_access{$scheme}) {
+ print "Unknown access scheme $scheme in $answer\n";
+ print " The available access methods known to me are\n";
+ print join (' ', @known_access), "\n";
+ print "\n";
+ }
+ else {
+ $rec->{'URN'} = $answer;
+ last;
+ }
+ }
+ }
+
+ print "\n";
+
+ print " Please give the distribution tag to get or a path to the\n";
+ print " package file ending in a /. The distribution\n";
+ print " tags are typically something like:$boldon ";
+ print join(' ', @typical_distributions), "$boldoff\n";
+ print "\n";
+ print "$boldon Distribution [$distribution]:$boldoff ";
+ $answer=<STDIN>;
+ chomp ($answer);
+ $answer =~ s/\s*//og;
+
+ if ($answer =~ /^\s*$/o) {
+ $rec->{'Distribution'} = $distribution;
+ $rec->{'Components'} = &get_components($components);
+ }
+ elsif ($answer =~ m|/$|o) {
+ $rec->{'Distribution'} = "$answer";
+ $rec->{'Components'} = "";
+ }
+ else {
+ # A distribution tag, eh?
+ warn "$answer does not seem to be a typical distribution tag\n"
+ unless defined $typical_distributions{$answer};
+
+ $rec->{'Distribution'} = "$answer";
+ $rec->{'Components'} = &get_components($components);
+ }
+
+ return $rec;
+}
+
+sub get_components {
+ my $default = shift;
+ my $answer;
+
+ print "\n";
+ print " Please give the components to get\n";
+ print " The components are typically something like:$boldon ";
+ print join(' ', @typical_components), "$boldoff\n";
+ print "\n";
+ print "$boldon Components [$default]:$boldoff ";
+ $answer=<STDIN>;
+ chomp ($answer);
+ $answer =~ s/\s+/ /og;
+
+ if ($answer =~ /^\s*$/o) {
+ return $default;
+ }
+ else {
+ return $answer;
+ }
+}
+
+sub get_sources {
+ my @Config = ();
+ my $done = 0;
+
+ my @Oldconfig = ();
+
+ if (-e $config_file) {
+ @Oldconfig = &read_config('Filename' => $config_file)
+ }
+
+ print "\t$boldon Set up a list of distribution source locations $boldoff \n";
+ print "\n";
+
+ print " Please give the base URL of the debian distribution.\n";
+ print " The access schemes I know about are:$boldon ";
+ print join (' ', @known_access), "$boldoff\n";
+# print " The mirror scheme is special that it does not specify the\n";
+# print " location of a debian archive but specifies the location\n";
+# print " of a list of mirrors to use to access the archive.\n";
+ print "\n";
+ print " For example:\n";
+ print " file:/mnt/debian,\n";
+ print " ftp://ftp.debian.org/debian,\n";
+ print " http://ftp.de.debian.org/debian,\n";
+# print " and the special mirror scheme,\n";
+# print " mirror:http://www.debian.org/archivemirrors \n";
+ print "\n";
+
+ my $index = 0;
+ while (!$done) {
+ if ($Oldconfig[$index]) {
+ push (@Config, &get_source('Default' => $Oldconfig[$index++]));
+ }
+ else {
+ push (@Config, &get_source());
+ }
+ print "\n";
+ print "$boldon Would you like to add another source?[y/N]$boldoff ";
+ my $answer = <STDIN>;
+ chomp ($answer);
+ $answer =~ s/\s+/ /og;
+ if ($answer =~ /^\s*$/o) {
+ last;
+ }
+ elsif ($answer !~ m/\s*y/io) {
+ last;
+ }
+ }
+
+ return @Config;
+}
+
+sub main {
+ if (-e $config_file) {
+ my @Oldconfig = &read_config('Filename' => $config_file);
+
+ print "$boldon I see you already have a source list.$boldoff\n";
+ print "-" x 72, "\n";
+ &print_config('Config' => \@Oldconfig);
+ print "-" x 72, "\n";
+ print "$boldon Do you wish to change it?[y/N]$boldoff ";
+ my $answer = <STDIN>;
+ chomp ($answer);
+ $answer =~ s/\s+/ /og;
+ exit 0 unless $answer =~ m/\s*y/io;
+ }
+ # OK. They want to be here.
+ my @Config = &get_sources();
+ #&print_config('Config' => \@Config);
+ &write_config('Config' => \@Config, 'Filename' => $config_file);
+}
+
+&main();
+
+
diff --git a/dselect/update b/dselect/update
new file mode 100755
index 000000000..ca507c4c6
--- /dev/null
+++ b/dselect/update
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -e
+
+# Get the configuration from /etc/apt/apt.conf
+OPTS="-f"
+APTGET="/usr/bin/apt-get"
+APTCACHE="/usr/bin/apt-cache"
+DPKG="/usr/bin/dpkg"
+CACHEDIR="/var/cache/apt"
+RES=`apt-config shell OPTS DSelect::UpdateOptions \
+ DPKG Dir::Bin::dpkg APTGET Dir::Bin::apt-get \
+ APTCACHE Dir::Bin::apt-cache CACHEDIR Dir::Cache`
+eval $RES
+
+$APTGET $OPTS update
+
+echo "Merging Available information"
+rm -f /var/cache/apt/available
+$APTCACHE dumpavail > $CACHEDIR/available
+$DPKG --update-avail $CACHEDIR/available
+rm -f $CACHEDIR/available
+exit 0