<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># needrestart - Restart daemons after library updates.
#
# Authors:
#   Thomas Liske &lt;thomas@fiasko-nw.net&gt;
#
# 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-&gt;{verbosity}: 1 if needrestart is in verbose mode, 0
# otherwise.
#
# $self-&gt;{progress}: if undef, disable the progress bar.  Otherwise:
#
#   $self-&gt;{progress}-&gt;{msg}: message to print (last message printed).
#
#   $self-&gt;{progress}-&gt;{count}: current progress (number of steps done
#   since the beginning).
#
#   $self-&gt;{progress}-&gt;{max}: Expected total number of steps.  If 0,
#   the bar will always be at 0.
#
# $self-&gt;{fhin}, $self-&gt;{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 =&gt; $verbosity,
	progress =&gt; undef,
    }, $class;
}

# my $nb_columns = _get_terminal_columns(FILEHANDLE);
# e.g.: my $nb_columns = _get_terminal_columns(\*STDOUT);
# =&gt; 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 = &amp;_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-&gt;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-&gt;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-&gt;{verbosity} != 1) || !(-t *STDERR)) {
	# restore terminal if required (debconf)
	unless(-t *STDIN) {
	    open($self-&gt;{fhin}, '&lt;&amp;', \*STDIN) || die "Can't dup stdin: $!\n";
	    open(STDIN, '&lt; /dev/tty') || open(STDIN, '&lt;&amp;1');
	}
	unless(-t *STDOUT) {
	    open($self-&gt;{fhout}, '&gt;&amp;', \*STDOUT) || die "Can't dup stdout: $!\n";
	    open(STDOUT, '&gt; /dev/tty') || open(STDOUT, '&gt;&amp;2');
	}

	$self-&gt;{progress} = {
	    count =&gt; 0,
	    max =&gt; $max,
	};
    }
    else {
	# disable progress indicator while being verbose
	$self-&gt;{progress} = undef;
    }

    $self-&gt;_progress_msg($out);
}

# $ui-&gt;progress_step();
#
# Add one step to the progress and update the display.
sub progress_step($) {
    my $self = shift;

    return unless defined($self-&gt;{progress});

    $self-&gt;_progress_inc();

    1;
}

# $ui-&gt;progress_fin();
#
# Restore stdin/out as they were before the preparation.
sub progress_fin($) {
    my $self = shift;

    return unless defined($self-&gt;{progress});

    $self-&gt;_progress_fin();

    # restore STDIN/STDOUT if required (debconf)
    open(STDIN, '&lt;&amp;', \*{$self-&gt;{fhin}}) || die "Can't dup stdin: $!\n"
	if($self-&gt;{fhin});
    open(STDOUT, '&gt;&amp;', \*{$self-&gt;{fhout}}) || die "Can't dup stdout: $!\n"
	if($self-&gt;{fhout});
}

# $ui-&gt;_progress_msg(MESSAGE);
#
# Set the current MESSAGE and update the display.
sub _progress_msg {
    my $self = shift;

    return unless defined($self-&gt;{progress});

    $self-&gt;{progress}-&gt;{msg} = shift;
    $self-&gt;_progress_out();
}

# $ui-&gt;_progress_inc();
#
# Increase progress by one step and redisplay.
sub _progress_inc {
    my $self = shift;

    $self-&gt;{progress}-&gt;{count}++;
    $self-&gt;_progress_out();
}

# $ui-&gt;_progress_out();
#
# Print the current message and progress bar.
sub _progress_out {
    my $self = shift;

    my $msg = $self-&gt;{progress}-&gt;{msg};
    my $max = $self-&gt;{progress}-&gt;{max};
    my $count = $self-&gt;{progress}-&gt;{count};

    # The line looks like this:
    # my message [====                ]
    # &lt;- wmsg -&gt;..&lt;---- wbar --------&gt;.

    # 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) &lt; $wmsg);

    my $wbar = $remaining_space - $wmsg;

    my $bar = '=' x ($wbar*( $max &gt; 0 ? $count/$max : 0 ));
    printf("%-${wmsg}s [%-${wbar}s]\r", substr($msg, 0, $wmsg), $bar);
}

# $ui-&gt;_progress_fin();
#
# Finish the progress.  Redisplay the line, removing the bar.
sub _progress_fin {
   my $self = shift;
   my $columns = _get_columns;

   $self-&gt;{progress}-&gt;{count} = 0;

   print $self-&gt;{progress}-&gt;{msg}, ' ' x ($columns - length($self-&gt;{progress}-&gt;{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-&gt;notice(@_);
}


sub query_pkgs($$$$$) {
}

sub query_conts($$$$$) {
}

sub runcmd {
    my $self = shift;
    my $cb = shift;

    &amp;$cb;
}

1;
</pre></body></html>