Codebase list debconf / 37c0d637-bb1a-489e-be1c-76e88cb5800e/main dpkg-reconfigure
37c0d637-bb1a-489e-be1c-76e88cb5800e/main

Tree @37c0d637-bb1a-489e-be1c-76e88cb5800e/main (Download .tar.gz)

dpkg-reconfigure @37c0d637-bb1a-489e-be1c-76e88cb5800e/mainraw · history · blame

#!/usr/bin/perl -w

=head1 NAME

dpkg-reconfigure - reconfigure an already installed package

=head1 SYNOPSIS

 dpkg-reconfigure [options] packages

=head1 DESCRIPTION

B<dpkg-reconfigure> reconfigures packages after they have already been
installed. Pass it the names of a package or packages to reconfigure. It
will ask configuration questions, much like when the package was first
installed.

If you just want to see the current configuration of a package, see
L<debconf-show(1)> instead.

=head1 OPTIONS

=over 4

=item B<-f>I<type>, B<--frontend=>I<type>

Select the frontend to use. The default frontend can be permanently changed
by:

 dpkg-reconfigure debconf

Note that if you normally have debconf set to use the noninteractive
frontend, dpkg-reconfigure will use the dialog frontend instead, so you
actually get to reconfigure the package.

=item B<-p>I<value>, B<--priority=>I<value>

Specify the minimum priority of question that will be displayed.
dpkg-reconfigure normally shows low priority questions no matter what your
default priority is. See L<debconf(7)> for a list.

=item B<--default-priority>

Use whatever the default priority of question is, instead of forcing the
priority to low.

=item B<-u>, B<--unseen-only>

By default, all questions are shown, even if they have already been
answered. If this parameter is set though, only questions that have not yet
been seen will be asked.

=item B<--force>

Force dpkg-reconfigure to reconfigure a package even if the package is in an
inconsistent or broken state. Use with caution.

=item B<--no-reload>

Prevent dpkg-reconfigure from reloading templates. Use with caution; this
will prevent dpkg-reconfigure from repairing broken templates databases.
However, it may be useful in constrained environments where rewriting the
templates database is expensive.

=item B<-h>, B<--help>

Display usage help.

=back

=cut

=head1 SEE ALSO

L<debconf(7)>

=cut

if (exists $ENV{DEBCONF_USE_CDEBCONF} and $ENV{DEBCONF_USE_CDEBCONF} ne '') {
    exec "/usr/lib/cdebconf/dpkg-reconfigure", @ARGV;
}

use strict;
use Cwd;
use Debconf::Db;
use Debconf::Gettext;
use Debconf::Template;
use Debconf::Config;
use Debconf::AutoSelect qw(:all);
use Debconf::Log qw(:all);

# Use low priority unless an option below overrides.
Debconf::Config->priority('low');

my $unseen_only=0;
my $force=0;
my $default_priority=0;
my $reload=1;
Debconf::Config->getopt(
gettext(qq{Usage: dpkg-reconfigure [options] packages
  -u,  --unseen-only		Show only not yet seen questions.
       --default-priority	Use default priority instead of low.
       --force			Force reconfiguration of broken packages.
       --no-reload		Do not reload templates. (Use with caution.)}),
	"unseen-only|u"		=> \$unseen_only,
	"default-priority"	=> \$default_priority,
	"force"			=> \$force,
	"reload!"		=> \$reload,
);

if ($> != 0) {
	print STDERR sprintf(gettext("%s must be run as root"), $0)."\n";
	exit 1;
}

Debconf::Db->load;

if ($default_priority) {
	Debconf::Config->priority(Debconf::Question->get('debconf/priority')->value);
}

# If the frontend is noninteractive, change it temporarily to dialog.
if (lc Debconf::Config->frontend eq 'noninteractive' &&
    ! Debconf::Config->frontend_forced) {
	Debconf::Config->frontend('dialog');
}

my $frontend=make_frontend();

unless ($unseen_only) {
	# Make the frontend show questions even if the user has already seen
	# them. Since this is a reconfigure program, they may want to change
	# their choices.
	Debconf::Config->reshow(1);
}

my @packages=@ARGV;
if (! @packages) {
	print STDERR "$0: ".gettext("please specify a package to reconfigure")."\n";
	exit 1;
}

# This is a hack to let postinsts know when they're being reconfigured. It
# would of course be better to pass them "reconfigure", but we can't for
# hysterical raisens.
$ENV{DEBCONF_RECONFIGURE}=1;

my %initial_triggers=map { $_ => 1 } triggers_pending();

my $original_cwd=getcwd();

foreach my $pkg (@packages) {
	# Set default title.
	$frontend->default_title($pkg);
	$frontend->info(undef);

	# Get the package version. Also check to make sure it is installed.
	$_=`dpkg --status $pkg`;
	my ($version)=m/Version: (.*)\n/;
	my ($status)=m/Status: (.*)\n/;
	my ($package)=m/Package: (.*)\n/;
	my ($arch)=m/Architecture: (.*)\n/;
	if (! $force) {
		if (! defined $status || $status =~ m/not-installed$/) {
			print STDERR "$0: ".sprintf(gettext("%s is not installed"), $pkg)."\n";
			exit 1;
		}
		if ($status !~ m/ ok installed$/) {
			print STDERR "$0: ".sprintf(gettext("%s is broken or not fully installed"), $pkg)."\n";
			exit 1;
		}
	}
	
	my @control_paths=`dpkg-query --control-path $pkg`;
	map chomp, @control_paths;
	my $control_path = sub {
		my $file = shift;
		my $path = (grep /\.\Q$file\E$/, @control_paths)[0];
		chomp($path) if defined $path;
		return $path;
	};

	if ($reload) {
		# Load up templates just in case they aren't already.
		my $templates=$control_path->('templates');
		if ($templates and -e $templates) {
			Debconf::Template->load($templates, $pkg);
		}
	}

	# Simulation of reinstalling a package, without bothering with
	# removing the files and putting them back. Just like in a regular
	# reinstall, run config, and postinst scripts in sequence, with args.
	# Do not run postrm, because the postrm can depend on the package's
	# files actually being gone already.
	foreach my $info (['prerm',    'upgrade',     $version],
		          ['config',   'reconfigure', $version],
			  ['postinst', 'configure',   $version]) {
		my $script=shift @$info;
		my $path_script=$control_path->($script);

		next unless $path_script and -x $path_script;

		my $is_confmodule='';

		# Set environment variables expected by maintainer scripts
		$ENV{DPKG_MAINTSCRIPT_PACKAGE}=$package;
		$ENV{DPKG_MAINTSCRIPT_ARCH}=$arch;
		$ENV{DPKG_MAINTSCRIPT_NAME}=$script;

		if ($script ne 'config') {
			# Test to see if the script uses debconf.
			open (IN, "<$path_script");
			while (<IN>) {
				if (/confmodule/i) {
					$is_confmodule=1;
					last;
				}
			}
			close IN;
		}
		
		chdir('/');
		if ($script eq 'config' || $is_confmodule) {
			# Start up the confmodule.
			my $confmodule=make_confmodule($path_script, @$info);
	
			# Make sure any questions the confmodule registers
			# are owned by this package.
			$confmodule->owner($pkg);
		
			# Talk to it until it is done.
			1 while ($confmodule->communicate);
	
			exit $confmodule->exitcode if $confmodule->exitcode > 0;
		}
		else {
			# Not a confmodule, so run it as a normal script.
			run_external($path_script, @$info);
		}
		chdir($original_cwd);
	}
}

# Maintainer scripts may have activated triggers.  If so, try to process
# them.
my @new_triggers;
do {
	@new_triggers=();
	foreach my $trigpend (triggers_pending()) {
		push @new_triggers, $trigpend
			if not exists $initial_triggers{$trigpend};
	}
	if (@new_triggers) {
		chdir('/');
		run_external("dpkg", "--configure", @new_triggers);
		chdir($original_cwd);
	}
} while (@new_triggers);

$frontend->shutdown;

Debconf::Db->save;

# Run an external program that does not itself use debconf, but that may run
# other programs that do use debconf.  To do this safely, checkpoint the
# current database state and re-initialize it when the program finishes.
sub run_external {
	Debconf::Db->save;
	
	delete $ENV{DEBIAN_HAS_FRONTEND};
	my $ret=system(@_);
	if (int($ret / 256) != 0) {
		exit int($ret / 256);
	}
	$ENV{DEBIAN_HAS_FRONTEND}=1;
	
	Debconf::Db->load;
}

# Returns a list of all packages with pending triggers.
sub triggers_pending {
	my @ret;
	local $_;

	open (QUERY, '-|', 'dpkg-query', '-W',
		'-f', '${Package} ${binary:Package}\t${Triggers-Pending}\n');
	while (<QUERY>) {
		chomp;
		my ($pkgnames, $triggers) = split /\t/;
		if (length $triggers) {
			# Handle multiarch.
			my ($pkg, $binpkg) = split ' ', $pkgnames;
			push @ret, (length $binpkg ? $binpkg : $pkg);
		}
	}
	close QUERY;

	return @ret;
}

=head1 AUTHOR

Joey Hess <joeyh@debian.org>

=cut