/[debconf]/trunk/src/debconf/debconf-apt-progress
ViewVC logotype

Contents of /trunk/src/debconf/debconf-apt-progress

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2349 - (hide annotations) (download)
Fri Jul 3 13:09:34 2009 UTC (3 years, 10 months ago) by cjwatson
File size: 18117 byte(s)
debconf-apt-progress: Handle cancellation right at the end. We don't
have a process to kill at this point, but we should at least return the
correct exit code.
1 cjwatson 1901 #!/usr/bin/perl -w
2    
3     =head1 NAME
4    
5     debconf-apt-progress - install packages using debconf to display a progress bar
6    
7     =head1 SYNOPSIS
8    
9     debconf-apt-progress [--] command [args ...]
10     debconf-apt-progress --config
11     debconf-apt-progress --start
12     debconf-apt-progress --from waypoint --to waypoint [--] command [args ...]
13     debconf-apt-progress --stop
14    
15     =head1 DESCRIPTION
16    
17     B<debconf-apt-progress> installs packages using debconf to display a
18     progress bar. The given I<command> should be any command-line apt frontend;
19     specifically, it must send progress information to the file descriptor
20     selected by the C<APT::Status-Fd> configuration option, and must keep the
21     file descriptors nominated by the C<APT::Keep-Fds> configuration option open
22     when invoking debconf (directly or indirectly), as those file descriptors
23     will be used for the debconf passthrough protocol.
24    
25     The arguments to the command you supply should generally include B<-y> (for
26     B<apt-get> or B<aptitude>) or similar to avoid the apt frontend prompting
27     for input. B<debconf-apt-progress> cannot do this itself because the
28     appropriate argument may differ between apt frontends.
29    
30     The B<--start>, B<--stop>, B<--from>, and B<--to> options may be used to
31     create a progress bar with multiple segments for different stages of
32     installation, provided that the caller is a debconf confmodule. The caller
33     may also interact with the progress bar itself using the debconf protocol if
34     it so desires.
35    
36     debconf locks its config database when it starts up, which makes it
37     unfortunately inconvenient to have one instance of debconf displaying the
38     progress bar and another passing through questions from packages being
39 cjwatson 1908 installed. If you're using a multiple-segment progress bar, you'll need to
40     eval the output of the B<--config> option before starting the debconf
41     frontend to work around this. See L<the EXAMPLES section/EXAMPLES> below.
42 cjwatson 1901
43     =head1 OPTIONS
44    
45     =over 4
46    
47     =item B<--config>
48    
49 cjwatson 1908 Print environment variables necessary to start up a progress bar frontend.
50 cjwatson 1901
51     =item B<--start>
52    
53 cjwatson 1912 Start up a progress bar, running from 0 to 100 by default. Use B<--from> and
54     B<--to> to use other endpoints.
55 cjwatson 1901
56     =item B<--from> I<waypoint>
57    
58 cjwatson 1912 If used with B<--start>, make the progress bar begin at I<waypoint> rather
59     than 0.
60 cjwatson 1901
61 cjwatson 1912 Otherwise, install packages with their progress bar beginning at this
62     "waypoint". Must be used with B<--to>.
63    
64 cjwatson 1901 =item B<--to> I<waypoint>
65    
66 cjwatson 1912 If used with B<--start>, make the progress bar end at I<waypoint> rather
67     than 100.
68 cjwatson 1901
69 cjwatson 1912 Otherwise, install packages with their progress bar ending at this
70     "waypoint". Must be used with B<--from>.
71    
72 cjwatson 1901 =item B<--stop>
73    
74     Stop a running progress bar.
75    
76 joeyh 2233 =item B<--no-progress>
77    
78     Avoid starting, stopping, or stepping the progress bar. Progress
79     messages from apt, media change events, and debconf questions will still
80     be passed through to debconf.
81    
82 joeyh 2244 =item B<--dlwaypoint> I<percentage>
83    
84     Specify what percent of the progress bar to use for downloading packages.
85     The remainder will be used for installing packages. The default is to use
86     15% for downloading and the remaining 85% for installing.
87    
88 cjwatson 1901 =item B<--logfile> I<file>
89    
90     Send the normal output from apt to the given file.
91    
92 cjwatson 1904 =item B<--logstderr>
93    
94     Send the normal output from apt to stderr. If you supply neither
95     B<--logfile> nor B<--logstderr>, the normal output from apt will be
96     discarded.
97    
98 cjwatson 1901 =item B<-->
99    
100     Terminate options. Since you will normally need to give at least the B<-y>
101     argument to the command being run, you will usually need to use B<--> to
102     prevent that being interpreted as an option to B<debconf-apt-progress>
103     itself.
104    
105 cjwatson 2307 =back
106    
107 cjwatson 1901 =head1 EXAMPLES
108    
109     Install the GNOME desktop and an X window system development environment
110     within a progress bar:
111    
112     debconf-apt-progress -- aptitude -y install gnome x-window-system-dev
113    
114     Install the GNOME, KDE, and XFCE desktops within a single progress bar,
115     allocating 45% of the progress bar for each of GNOME and KDE and the
116     remaining 10% for XFCE:
117    
118     #! /bin/sh
119     set -e
120     case $1 in
121     '')
122 cjwatson 1908 eval "$(debconf-apt-progress --config)"
123     "$0" debconf
124 cjwatson 1901 ;;
125     debconf)
126     . /usr/share/debconf/confmodule
127     debconf-apt-progress --start
128     debconf-apt-progress --from 0 --to 45 -- apt-get -y install gnome
129     debconf-apt-progress --from 45 --to 90 -- apt-get -y install kde
130     debconf-apt-progress --from 90 --to 100 -- apt-get -y install xfce4
131     debconf-apt-progress --stop
132     ;;
133     esac
134    
135 joeyh 2238 =head1 RETURN CODE
136    
137     The exit code of the specified command is returned, unless the user hit the
138     cancel button on the progress bar. If the cancel button was hit, a value of
139 joeyh 2239 30 is returned. To avoid ambiguity, if the command returned 30, a value of
140     3 will be returned.
141 joeyh 2238
142 cjwatson 1901 =cut
143    
144     use strict;
145     use POSIX;
146     use Fcntl;
147     use Getopt::Long;
148     # Avoid starting the debconf frontend just yet.
149     use Debconf::Client::ConfModule ();
150    
151     my ($config, $start, $from, $to, $stop);
152 joeyh 2233 my $progress=1;
153 joeyh 2244 my $dlwaypoint=15;
154 cjwatson 1904 my ($logfile, $logstderr);
155 cjwatson 2343 my $had_frontend;
156 cjwatson 1901
157     sub checkopen (@) {
158     my $file = $_[0];
159     my $fd = POSIX::open($file, &POSIX::O_RDONLY);
160     defined $fd or die "$0: can't open $_[0]: $!\n";
161     return $fd;
162     }
163    
164     sub checkclose ($) {
165     my $fd = $_[0];
166     unless (POSIX::close($fd)) {
167     return if $! == &POSIX::EBADF;
168     die "$0: can't close fd $fd: $!\n";
169     }
170     }
171    
172     sub checkdup2 ($$) {
173     my ($oldfd, $newfd) = @_;
174     checkclose($newfd);
175     POSIX::dup2($oldfd, $newfd)
176     or die "$0: can't dup fd $oldfd to $newfd: $!\n";
177     }
178    
179     sub nocloexec (*) {
180     my $fh = shift;
181     my $flags = fcntl($fh, F_GETFD, 0);
182     fcntl($fh, F_SETFD, $flags & ~FD_CLOEXEC);
183     }
184    
185 cjwatson 2214 sub nonblock (*) {
186     my $fh = shift;
187     my $flags = fcntl($fh, F_GETFL, 0);
188     fcntl($fh, F_SETFL, $flags | O_NONBLOCK);
189     }
190    
191 cjwatson 1901 # Open the given file descriptors to make sure they won't accidentally be
192     # used by Perl, leading to confusion.
193     sub reservefds (@) {
194     my $null = checkopen('/dev/null');
195     my $close = 1;
196     for my $fd (@_) {
197     if ($null == $fd) {
198     $close = 0;
199     } else {
200     checkclose($fd);
201     checkdup2($null, $fd);
202     }
203     }
204     if ($close) {
205     checkclose($null);
206     }
207     }
208    
209 cjwatson 1908 # Does this environment variable exist, and is it non-empty?
210     sub envnonempty ($) {
211     my $name = shift;
212     return (exists $ENV{$name} and $ENV{$name} ne '');
213     }
214    
215 cjwatson 1928 sub start_debconf (@) {
216     if (! $ENV{DEBIAN_HAS_FRONTEND}) {
217     # Save existing environment variables.
218     if (envnonempty('DEBCONF_DB_REPLACE')) {
219     $ENV{DEBCONF_APT_PROGRESS_DB_REPLACE} =
220     $ENV{DEBCONF_DB_REPLACE};
221     }
222     if (envnonempty('DEBCONF_DB_OVERRIDE')) {
223     $ENV{DEBCONF_APT_PROGRESS_DB_OVERRIDE} =
224     $ENV{DEBCONF_DB_OVERRIDE};
225     }
226    
227     # Make sure the main configdb is opened read-only ...
228     $ENV{DEBCONF_DB_REPLACE} = 'configdb';
229     # ... and stack a writable db on top of it, since the
230     # passthrough instance is going to be sending us db updates.
231     $ENV{DEBCONF_DB_OVERRIDE} = 'Pipe{infd:none outfd:none}';
232    
233 cjwatson 2343 # Leave a note for ourselves. We need to do it this way
234     # round since DEBIAN_HAS_FRONTEND will be set the second
235     # time round even if it isn't set initially.
236     $ENV{DEBCONF_APT_PROGRESS_NO_FRONTEND} = 1;
237 cjwatson 2334
238 cjwatson 1928 # Restore @ARGV so that
239     # Debconf::Client::ConfModule::import() can use it.
240     @ARGV = @_;
241     }
242    
243     import Debconf::Client::ConfModule;
244     }
245    
246 cjwatson 1901 sub passthrough (@) {
247     my $priority = Debconf::Client::ConfModule::get('debconf/priority');
248    
249     defined(my $pid = fork) or die "$0: can't fork: $!\n";
250     if (!$pid) {
251     close STATUS_READ;
252 joeyh 2105 close COMMAND_WRITE;
253 cjwatson 2214 close DEBCONF_COMMAND_READ;
254     close DEBCONF_REPLY_WRITE;
255 cjwatson 1901 $^F = 6; # avoid close-on-exec
256 joeyh 2105 if (fileno(COMMAND_READ) != 0) {
257     checkdup2(fileno(COMMAND_READ), 0);
258     close COMMAND_READ;
259 cjwatson 1901 }
260     if (fileno(APT_LOG) != 1) {
261     checkclose(1);
262     checkdup2(fileno(APT_LOG), 1);
263     }
264     if (fileno(APT_LOG) != 2) {
265     checkclose(2);
266     checkdup2(fileno(APT_LOG), 2);
267     }
268     close APT_LOG;
269     delete $ENV{DEBIAN_HAS_FRONTEND};
270     delete $ENV{DEBCONF_REDIR};
271     delete $ENV{DEBCONF_SYSTEMRC};
272     delete $ENV{DEBCONF_PIPE}; # just in case ...
273     $ENV{DEBIAN_FRONTEND} = 'passthrough';
274     $ENV{DEBIAN_PRIORITY} = $priority;
275     $ENV{DEBCONF_READFD} = 5;
276     $ENV{DEBCONF_WRITEFD} = 6;
277     $ENV{APT_LISTCHANGES_FRONTEND} = 'none';
278 cjwatson 2341 # If we already had a debconf frontend when we started, then
279     # the passthrough child needs to use the same pipe-database
280     # trick as we do. See start_debconf.
281 cjwatson 2343 if ($had_frontend) {
282 cjwatson 2341 $ENV{DEBCONF_DB_REPLACE} = 'configdb';
283     $ENV{DEBCONF_DB_OVERRIDE} = 'Pipe{infd:none outfd:none}';
284     }
285 cjwatson 1901 exec @_;
286     }
287    
288     close STATUS_WRITE;
289 joeyh 2105 close COMMAND_READ;
290 cjwatson 2214 close DEBCONF_COMMAND_WRITE;
291     close DEBCONF_REPLY_READ;
292 cjwatson 1901 return $pid;
293     }
294    
295 cjwatson 2214 sub handle_status ($$$) {
296     my ($from, $to, $line) = @_;
297     my ($status, $pkg, $percent, $description) = split ':', $line, 4;
298    
299     my ($min, $len);
300     if ($status eq 'dlstatus') {
301     $min = 0;
302 joeyh 2244 $len = $dlwaypoint;
303 cjwatson 2214 }
304     elsif ($status eq 'pmstatus') {
305 joeyh 2244 $min = $dlwaypoint;
306     $len = 100 - $dlwaypoint;
307 cjwatson 2214 }
308     elsif ($status eq 'media-change') {
309     Debconf::Client::ConfModule::subst(
310     'debconf-apt-progress/media-change', 'MESSAGE',
311     $description);
312     my @ret = Debconf::Client::ConfModule::input(
313     'critical', 'debconf-apt-progress/media-change');
314     $ret[0] == 0 or die "Can't display media change request!\n";
315     Debconf::Client::ConfModule::go();
316     print COMMAND_WRITE "\n" || die "can't talk to command fd: $!";
317 cjwatson 2266 return;
318 cjwatson 2214 }
319     else {
320 cjwatson 2266 return;
321 cjwatson 2214 }
322    
323     $percent = ($percent * $len / 100 + $min);
324     $percent = ($percent * ($to - $from) / 100 + $from);
325     $percent =~ s/\..*//;
326 joeyh 2236 if ($progress) {
327     my @ret=Debconf::Client::ConfModule::progress('SET', $percent);
328     if ($ret[0] eq '30') {
329     cancel();
330     }
331     }
332 cjwatson 2214 Debconf::Client::ConfModule::subst(
333     'debconf-apt-progress/info', 'DESCRIPTION', $description);
334 joeyh 2236 my @ret=Debconf::Client::ConfModule::progress(
335 cjwatson 2214 'INFO', 'debconf-apt-progress/info');
336 joeyh 2236 if ($ret[0] eq '30') {
337     cancel();
338     }
339 cjwatson 2214 }
340    
341     sub handle_debconf_command ($) {
342     my $line = shift;
343    
344     # Debconf::Client::ConfModule has already dealt with checking
345     # DEBCONF_REDIR.
346     print "$line\n" || die "can't write to stdout: $!";
347     my $ret = <STDIN>;
348     chomp $ret;
349     print DEBCONF_REPLY_WRITE "$ret\n" ||
350     die "can't write to DEBCONF_REPLY_WRITE: $!";
351     }
352    
353 joeyh 2236 my $pid;
354 cjwatson 1901 sub run_progress ($$@) {
355     my $from = shift;
356     my $to = shift;
357     my $command = shift;
358     local (*STATUS_READ, *STATUS_WRITE);
359 joeyh 2105 local (*COMMAND_READ, *COMMAND_WRITE);
360 cjwatson 2214 local (*DEBCONF_COMMAND_READ, *DEBCONF_COMMAND_WRITE);
361     local (*DEBCONF_REPLY_READ, *DEBCONF_REPLY_WRITE);
362 cjwatson 1901 local *APT_LOG;
363 cjwatson 2214 use IO::Handle;
364 cjwatson 1901
365 joeyh 2236 if ($progress) {
366     my @ret=Debconf::Client::ConfModule::progress(
367     'INFO', 'debconf-apt-progress/preparing');
368     if ($ret[0] eq '30') {
369     cancel();
370 cjwatson 2348 return 30;
371 joeyh 2236 }
372     }
373 cjwatson 1901
374     reservefds(4, 5, 6);
375    
376 cjwatson 2214 pipe STATUS_READ, STATUS_WRITE
377     or die "$0: can't create status pipe: $!";
378     nonblock(\*STATUS_READ);
379 cjwatson 1901 checkdup2(fileno(STATUS_WRITE), 4);
380     open STATUS_WRITE, '>&=4'
381     or die "$0: can't reopen STATUS_WRITE as fd 4: $!";
382     nocloexec(\*STATUS_WRITE);
383 cjwatson 2214
384     pipe COMMAND_READ, COMMAND_WRITE
385     or die "$0: can't create command pipe: $!";
386 joeyh 2105 nocloexec(\*COMMAND_READ);
387     COMMAND_WRITE->autoflush(1);
388 cjwatson 1901
389 cjwatson 2214 pipe DEBCONF_COMMAND_READ, DEBCONF_COMMAND_WRITE
390     or die "$0: can't create debconf command pipe: $!";
391     nonblock(\*DEBCONF_COMMAND_READ);
392     checkdup2(fileno(DEBCONF_COMMAND_WRITE), 6);
393     open DEBCONF_COMMAND_WRITE, '>&=6'
394     or die "$0: can't reopen DEBCONF_COMMAND_WRITE as fd 6: $!";
395     nocloexec(\*DEBCONF_COMMAND_WRITE);
396    
397     pipe DEBCONF_REPLY_READ, DEBCONF_REPLY_WRITE
398     or die "$0: can't create debconf reply pipe: $!";
399     checkdup2(fileno(DEBCONF_REPLY_READ), 5);
400     open DEBCONF_REPLY_READ, '<&=5'
401     or die "$0: can't reopen DEBCONF_REPLY_READ as fd 5: $!";
402     nocloexec(\*DEBCONF_REPLY_READ);
403     DEBCONF_REPLY_WRITE->autoflush(1);
404    
405 cjwatson 1901 if (defined $logfile) {
406     open APT_LOG, '>>', $logfile
407     or die "$0: can't open $logfile: $!";
408 cjwatson 1904 } elsif ($logstderr) {
409 cjwatson 1901 open APT_LOG, '>&STDERR'
410     or die "$0: can't duplicate stderr: $!";
411 cjwatson 1904 } else {
412     open APT_LOG, '>', '/dev/null'
413     or die "$0: can't open /dev/null: $!";
414 cjwatson 1901 }
415     nocloexec(\*APT_LOG);
416    
417 joeyh 2236 $pid = passthrough $command,
418 cjwatson 1901 '-o', 'APT::Status-Fd=4',
419     '-o', 'APT::Keep-Fds::=5',
420     '-o', 'APT::Keep-Fds::=6',
421     @_;
422    
423 cjwatson 2214 my $status_eof = 0;
424     my $debconf_command_eof = 0;
425     my $status_buf = '';
426     my $debconf_command_buf = '';
427 cjwatson 1901
428 cjwatson 2249 # STATUS_READ should be the last fd to close. DEBCONF_COMMAND_WRITE
429     # may end up captured by buggy daemons, so terminate the loop even
430     # if we haven't hit $debconf_command_eof.
431     while (not $status_eof) {
432 cjwatson 2214 my $rin = '';
433     my $rout;
434 cjwatson 2249 vec($rin, fileno(STATUS_READ), 1) = 1;
435 cjwatson 2214 vec($rin, fileno(DEBCONF_COMMAND_READ), 1) = 1
436     unless $debconf_command_eof;
437     my $sel = select($rout = $rin, undef, undef, undef);
438     if ($sel < 0) {
439     next if $! == &POSIX::EINTR;
440     die "$0: select failed: $!";
441 joeyh 2119 }
442 cjwatson 2214
443     if (vec($rout, fileno(STATUS_READ), 1) == 1) {
444     # Status message from apt. Transform into debconf
445     # messages.
446     while (1) {
447     my $r = sysread(STATUS_READ, $status_buf, 4096,
448     length $status_buf);
449     if (not defined $r) {
450     next if $! == &POSIX::EINTR;
451     last if $! == &POSIX::EAGAIN or
452     $! == &POSIX::EWOULDBLOCK;
453     die "$0: read STATUS_READ failed: $!";
454     }
455     elsif ($r == 0) {
456     if ($status_buf ne '' and
457     $status_buf !~ /\n$/) {
458     $status_buf .= "\n";
459     }
460     $status_eof = 1;
461     last;
462     }
463     last if $status_buf =~ /\n/;
464     }
465    
466     while ($status_buf =~ /\n/) {
467     my $status_line;
468     ($status_line, $status_buf) =
469     split /\n/, $status_buf, 2;
470     handle_status $from, $to, $status_line;
471     }
472 joeyh 2119 }
473 cjwatson 2214
474     if (vec($rout, fileno(DEBCONF_COMMAND_READ), 1) == 1) {
475     # Debconf command. Pass straight through.
476     while (1) {
477     my $r = sysread(DEBCONF_COMMAND_READ,
478     $debconf_command_buf, 4096,
479     length $debconf_command_buf);
480     if (not defined $r) {
481     next if $! == &POSIX::EINTR;
482     last if $! == &POSIX::EAGAIN or
483     $! == &POSIX::EWOULDBLOCK;
484     die "$0: read DEBCONF_COMMAND_READ " .
485     "failed: $!";
486     }
487     elsif ($r == 0) {
488     if ($debconf_command_buf ne '' and
489     $debconf_command_buf !~ /\n$/) {
490     $debconf_command_buf .= "\n";
491     }
492     $debconf_command_eof = 1;
493     last;
494     }
495     last if $debconf_command_buf =~ /\n/;
496     }
497    
498     while ($debconf_command_buf =~ /\n/) {
499     my $debconf_command_line;
500     ($debconf_command_line, $debconf_command_buf) =
501     split /\n/, $debconf_command_buf, 2;
502     handle_debconf_command $debconf_command_line;
503     }
504 joeyh 2119 }
505 cjwatson 1901 }
506    
507     waitpid $pid, 0;
508 cjwatson 2349 undef $pid;
509 cjwatson 1901 my $status = $?;
510    
511     # make sure that the progress bar always gets to the end
512 cjwatson 2349 if ($progress) {
513     my @ret=Debconf::Client::ConfModule::progress('SET', $to);
514     if ($ret[0] eq '30') {
515     cancel();
516     }
517     }
518 cjwatson 1901
519 joeyh 2237 if ($status & 127) {
520     return 127;
521     }
522    
523 cjwatson 1901 return ($status >> 8);
524     }
525    
526 joeyh 2244 # Called if the progress bar is cancelled. Starts with a SIGINT but
527 joeyh 2236 # if called repeatedly, falls back to SIGKILL.
528 joeyh 2240 my $cancelled=0;
529 cjwatson 2348 my $cancel_sent_signal=0;
530 joeyh 2236 sub cancel () {
531 cjwatson 2348 $cancelled++;
532 joeyh 2236 if (defined $pid) {
533 cjwatson 2348 $cancel_sent_signal++;
534     if ($cancel_sent_signal == 1) {
535 cjwatson 2265 kill INT => $pid;
536 joeyh 2236 }
537     else {
538 cjwatson 2265 kill KILL => $pid;
539 joeyh 2236 }
540     }
541     }
542    
543 cjwatson 1912 sub start_bar ($$) {
544     my ($from, $to) = @_;
545 joeyh 2236 if ($progress) {
546     Debconf::Client::ConfModule::progress(
547     'START', $from, $to, 'debconf-apt-progress/title');
548     my @ret=Debconf::Client::ConfModule::progress(
549     'INFO', 'debconf-apt-progress/preparing');
550     if ($ret[0] eq '30') {
551     cancel();
552     }
553     }
554 cjwatson 1901 }
555    
556     sub stop_bar () {
557 joeyh 2233 Debconf::Client::ConfModule::progress('STOP') if $progress;
558 cjwatson 1909 # If we don't stop, we leave a zombie in case some daemon fails to
559 cjwatson 2334 # disconnect from fd 3. Don't do this if debconf was already
560     # running, though, since in that case we're running as part of a
561     # larger application which will need to take its own care to stop
562     # when it's finished.
563 cjwatson 2343 Debconf::Client::ConfModule::stop() unless $had_frontend;
564 cjwatson 1901 }
565    
566 cjwatson 1908 # Restore saved environment variables.
567     if (envnonempty('DEBCONF_APT_PROGRESS_DB_REPLACE')) {
568     $ENV{DEBCONF_DB_REPLACE} = $ENV{DEBCONF_APT_PROGRESS_DB_REPLACE};
569     } else {
570     delete $ENV{DEBCONF_DB_REPLACE};
571     }
572     if (envnonempty('DEBCONF_APT_PROGRESS_DB_OVERRIDE')) {
573     $ENV{DEBCONF_DB_OVERRIDE} = $ENV{DEBCONF_APT_PROGRESS_DB_OVERRIDE};
574     } else {
575     delete $ENV{DEBCONF_DB_OVERRIDE};
576     }
577 cjwatson 2343 $had_frontend = 1 unless $ENV{DEBCONF_APT_PROGRESS_NO_FRONTEND};
578     delete $ENV{DEBCONF_APT_PROGRESS_NO_FRONTEND}; # avoid inheritance
579 cjwatson 1908
580 cjwatson 1901 my @saved_argv = @ARGV;
581    
582 joeyh 2244 my $result = GetOptions('config' => \$config,
583     'start' => \$start,
584     'from=i' => \$from,
585     'to=i' => \$to,
586     'stop' => \$stop,
587     'logfile=s' => \$logfile,
588     'logstderr' => \$logstderr,
589     'progress!' => \$progress,
590     'dlwaypoint=i' => \$dlwaypoint,
591     );
592 cjwatson 1901
593 joeyh 2233 if (! $progress && ($start || $from || $to || $stop)) {
594     die "--no-progress cannot be used with --start, --from, --to, or --stop\n";
595     }
596    
597 cjwatson 1912 unless ($start) {
598     if (defined $from and not defined $to) {
599     die "$0: --from requires --to\n";
600     } elsif (defined $to and not defined $from) {
601     die "$0: --to requires --from\n";
602     }
603 cjwatson 1901 }
604    
605     my $mutex = 0;
606     ++$mutex if $config;
607     ++$mutex if $start;
608     ++$mutex if $stop;
609     if ($mutex > 1) {
610 cjwatson 1912 die "$0: must use only one of --config, --start, or --stop\n";
611 cjwatson 1901 }
612    
613 cjwatson 1912 if (($config or $stop) and (defined $from or defined $to)) {
614     die "$0: cannot use --from or --to with --config or --stop\n";
615     }
616    
617 cjwatson 1928 start_debconf(@saved_argv) unless $config;
618    
619 cjwatson 1901 my $status = 0;
620    
621     if ($config) {
622 cjwatson 1908 print <<'EOF';
623     DEBCONF_APT_PROGRESS_DB_REPLACE="$DEBCONF_DB_REPLACE"
624     DEBCONF_APT_PROGRESS_DB_OVERRIDE="$DEBCONF_DB_OVERRIDE"
625     export DEBCONF_APT_PROGRESS_DB_REPLACE DEBCONF_APT_PROGRESS_DB_OVERRIDE
626     DEBCONF_DB_REPLACE=configdb
627     DEBCONF_DB_OVERRIDE='Pipe{infd:none outfd:none}'
628     export DEBCONF_DB_REPLACE DEBCONF_DB_OVERRIDE
629     EOF
630 cjwatson 1901 } elsif ($start) {
631 cjwatson 1912 $from = 0 unless defined $from;
632     $to = 100 unless defined $to;
633     start_bar($from, $to);
634 cjwatson 1901 } elsif (defined $from) {
635     $status = run_progress($from, $to, @ARGV);
636     } elsif ($stop) {
637     stop_bar();
638     } else {
639 cjwatson 1912 start_bar(0, 100);
640 cjwatson 2348 if (! $cancelled) {
641     $status = run_progress(0, 100, @ARGV);
642     stop_bar();
643     }
644 cjwatson 1901 }
645    
646 joeyh 2240 if ($cancelled) {
647 joeyh 2245 # This is pure paranoia. What if the child was in the
648     # middle of writing a debconf command out, only to be
649     # interrupted with a truncated write? Let's send a no-op
650     # command to finish it out just in case.
651     Debconf::Client::ConfModule::get("debconf/priority");
652    
653 joeyh 2238 exit 30;
654     }
655 joeyh 2239 elsif ($status == 30) {
656     exit 3;
657     }
658 joeyh 2238 else {
659     exit $status;
660     }
661 cjwatson 1901
662     =head1 AUTHORS
663    
664     Colin Watson <cjwatson@debian.org>
665    
666     Joey Hess <joeyh@debian.org>
667    
668     =cut

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.5