~cjwatson/debconf/dbus

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#!/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<-a>, B<--all>

Reconfigure all installed packages that use debconf. Warning: this may take
a long time.

=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

my $infodir="/var/lib/dpkg/info";

use strict;
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 $all=0;
my $force=0;
my $default_priority=0;
my $reload=1;
Debconf::Config->getopt(
gettext(qq{Usage: dpkg-reconfigure [options] packages
  -a,  --all			Reconfigure all 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.)}),
	"all|a"			=> \$all,
	"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;
if ($all) {
	@packages=allpackages();
	exit unless @packages;
}
else {
	@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;

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/;
	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;
		}
	}
	
	if ($reload) {
		# Load up templates just in case they aren't already.
		Debconf::Template->load("$infodir/$pkg.templates", $pkg)
			if -e "$infodir/$pkg.templates";
	}

	# 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;
		next unless -x "$infodir/$pkg.$script";

		my $is_confmodule='';

		if ($script ne 'config') {
			# Test to see if the script uses debconf.
			open (IN, "<$infodir/$pkg.$script");
			while (<IN>) {
				if (/confmodule/i) {
					$is_confmodule=1;
					last;
				}
			}
			close IN;
		}
		
		if ($script eq 'config' || $is_confmodule) {
			# Start up the confmodule.
			my $confmodule=make_confmodule(
				"$infodir/$pkg.$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.
			# Since it might run other programs that do use
			# debconf, checkpoint the current database state
			# and re-initialize it when the script finishes.
			Debconf::Db->save;
			
			delete $ENV{DEBIAN_HAS_FRONTEND};
			my $ret=system("$infodir/$pkg.$script", @$info);
			if (int($ret / 256) != 0) {
				exit int($ret / 256);
			}
			$ENV{DEBIAN_HAS_FRONTEND}=1;
			
			Debconf::Db->load;
		}
	}
}

$frontend->shutdown;

Debconf::Db->save;

# Returns a list of all installed packages.
sub allpackages {
	my @ret;
	local $/="\n\n";
	
	open (STATUS, "</var/lib/dpkg/status")
		|| die sprintf(gettext("Cannot read status file: %s"), $!);
	while (<STATUS>) {
		push @ret, $1
			if m/Status:\s*.*\sinstalled\n/ && m/Package:\s*(.*)\n/;
	}
	close STATUS;

	return sort @ret;
}

=head1 AUTHOR

Joey Hess <joeyh@debian.org>

=cut