Linux lhjmq-records 5.15.0-118-generic #128-Ubuntu SMP Fri Jul 5 09:28:59 UTC 2024 x86_64
Your IP : 3.141.27.70
# needrestart - Restart daemons after library updates.
#
# Authors:
# Thomas Liske <thomas@fiasko-nw.net>
#
# Copyright Holder:
# 2013 - 2020 (C) Thomas Liske [http://fiasko-nw.net/~thomas/]
#
# License:
# 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 package; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
package NeedRestart::UI;
use strict;
use warnings;
use Text::Wrap qw(wrap);
use Term::ReadKey;
# NeedRestart::UI internals properties
# ====================================
#
# $self->{verbosity}: 1 if needrestart is in verbose mode, 0
# otherwise.
#
# $self->{progress}: if undef, disable the progress bar. Otherwise:
#
# $self->{progress}->{msg}: message to print (last message printed).
#
# $self->{progress}->{count}: current progress (number of steps done
# since the beginning).
#
# $self->{progress}->{max}: Expected total number of steps. If 0,
# the bar will always be at 0.
#
# $self->{fhin}, $self->{fhout}: original stdin/stdout filehandles.
# NeedRestart::UI may change the filehandles to ensure we have a
# terminal. The original filehandles are saved in these two
# attributes in progress_prep, and restored in progress_fin.
# my $ui = new NeedRestart::UI(VERBOSITY);
#
# VERBOSITY indicates whether needrestart is otherwise verbose (0 or
# 1). If VERBOSITY is 1, we disable the progress indicator:
# otherwise, the output would not be nice.
sub new {
my $class = shift;
my $verbosity = shift;
return bless {
verbosity => $verbosity,
progress => undef,
}, $class;
}
# my $nb_columns = _get_terminal_columns(FILEHANDLE);
# e.g.: my $nb_columns = _get_terminal_columns(\*STDOUT);
# => 103
#
# This is a wrapper for GetTerminalSize to cope with Debian
# Bug#824564.
sub _get_terminal_columns {
my ($filehandle) = @_;
# workaround Debian Bug#824564 in Term::ReadKey: pass filehandle
# twice
my ($columns) = GetTerminalSize($filehandle, $filehandle);
return $columns;
}
# my $columns = &_get_columns();
#
# Return the number of columns to use for output.
sub _get_columns {
my $default_columns = 80; # Sane default
if (-t *STDOUT) {
my ($columns) = _get_terminal_columns(\*STDOUT);
# Cope with 0-width terminals (see Debian bug #942759).
return $columns == 0? $default_columns: $columns;
}
else {
return $default_columns;
}
}
# $ui->wprint(FILEHANDLE, SP1, SP2, MESSAGE);
#
# Print the MESSAGE to the given FILEHANDLE, wrapping text if we can get
# the number of columns.
#
# SP1 and SP2 are resp. Text::Wrap::wrap's $initial_tab and
# $subsequent_tab.
sub wprint {
my $self = shift;
my $fh = shift;
my $sp1 = shift;
my $sp2 = shift;
my $message = shift;
# only wrap output if it is a terminal
if (-t $fh) {
my ($cols) = _get_terminal_columns($fh, $fh);
$Text::Wrap::columns = $cols? $cols: 80;
print $fh wrap($sp1, $sp2, $message);
}
else {
print $fh "$sp1$message";
}
}
# $ui->progress_prep(MAX, OUT);
#
# Prepare for displaying a new progress bar.
#
# Disable the progress bar if we don't have a terminal. Restore the
# terminal if necessary. Reset the progress counter. Print the
# initial line.
#
# MAX: expected total number of steps.
#
# OUT: the message, e.g. "Scanning processes..."
sub progress_prep($$$) {
my $self = shift;
my ($max, $out) = @_;
unless(($self->{verbosity} != 1) || !(-t *STDERR)) {
# restore terminal if required (debconf)
unless(-t *STDIN) {
open($self->{fhin}, '<&', \*STDIN) || die "Can't dup stdin: $!\n";
open(STDIN, '< /dev/tty') || open(STDIN, '<&1');
}
unless(-t *STDOUT) {
open($self->{fhout}, '>&', \*STDOUT) || die "Can't dup stdout: $!\n";
open(STDOUT, '> /dev/tty') || open(STDOUT, '>&2');
}
$self->{progress} = {
count => 0,
max => $max,
};
}
else {
# disable progress indicator while being verbose
$self->{progress} = undef;
}
$self->_progress_msg($out);
}
# $ui->progress_step();
#
# Add one step to the progress and update the display.
sub progress_step($) {
my $self = shift;
return unless defined($self->{progress});
$self->_progress_inc();
1;
}
# $ui->progress_fin();
#
# Restore stdin/out as they were before the preparation.
sub progress_fin($) {
my $self = shift;
return unless defined($self->{progress});
$self->_progress_fin();
# restore STDIN/STDOUT if required (debconf)
open(STDIN, '<&', \*{$self->{fhin}}) || die "Can't dup stdin: $!\n"
if($self->{fhin});
open(STDOUT, '>&', \*{$self->{fhout}}) || die "Can't dup stdout: $!\n"
if($self->{fhout});
}
# $ui->_progress_msg(MESSAGE);
#
# Set the current MESSAGE and update the display.
sub _progress_msg {
my $self = shift;
return unless defined($self->{progress});
$self->{progress}->{msg} = shift;
$self->_progress_out();
}
# $ui->_progress_inc();
#
# Increase progress by one step and redisplay.
sub _progress_inc {
my $self = shift;
$self->{progress}->{count}++;
$self->_progress_out();
}
# $ui->_progress_out();
#
# Print the current message and progress bar.
sub _progress_out {
my $self = shift;
my $msg = $self->{progress}->{msg};
my $max = $self->{progress}->{max};
my $count = $self->{progress}->{count};
# The line looks like this:
# my message [==== ]
# <- wmsg ->..<---- wbar -------->.
# 3 columns are preassigned (the space and the square brackets);
# we need to split the remaining space between the message and the
# bar itself.
my $remaining_space = _get_columns() - 3;
# We use 70% max of the remaining space.
my $wmsg = int($remaining_space * 0.7);
# Shrink if the message is actually shorter.
$wmsg = length($msg) if(length($msg) < $wmsg);
my $wbar = $remaining_space - $wmsg;
my $bar = '=' x ($wbar*( $max > 0 ? $count/$max : 0 ));
printf("%-${wmsg}s [%-${wbar}s]\r", substr($msg, 0, $wmsg), $bar);
}
# $ui->_progress_fin();
#
# Finish the progress. Redisplay the line, removing the bar.
sub _progress_fin {
my $self = shift;
my $columns = _get_columns;
$self->{progress}->{count} = 0;
print $self->{progress}->{msg}, ' ' x ($columns - length($self->{progress}->{msg})), "\n";
}
sub announce_abi {
}
sub announce_ver {
}
sub announce_ucode {
}
sub notice($$) {
}
sub vspace {
my $self = shift;
my $fh = shift;
print $fh "\n" if(defined($fh));
}
sub command() {
my $self = shift;
$self->notice(@_);
}
sub query_pkgs($$$$$) {
}
sub query_conts($$$$$) {
}
sub runcmd {
my $self = shift;
my $cb = shift;
&$cb;
}
1;
|