Files
webmin/grub2/install.cgi

148 lines
4.2 KiB
Perl
Executable File

#!/usr/local/bin/perl
# Install the GRUB 2 boot loader with progress output.
use strict;
use warnings;
require './grub2-lib.pl'; ## no critic
our (%in, %text);
&ReadParse();
&error_setup($text{'install_err'});
my %access = &get_module_acl();
&error("$text{'eacl_np'} $text{'eacl_pinstall'}") if (!$access{'install'});
# Trim text fields before validation so shell arguments are deterministic.
foreach my $field (qw(target efi_dir platform directory boot_directory
bootloader_id)) {
$in{$field} = "" if (!defined($in{$field}));
$in{$field} =~ s/^\s+|\s+\z//g;
}
&error($text{'install_eboot_directory_required'})
if ($in{'use_boot_directory'} && $in{'boot_directory'} eq '');
my %opts = (
'target' => $in{'target'},
'efi_dir' => $in{'efi_dir'},
'platform' => $in{'platform'} || &grub2_default_platform_target(),
'directory' => $in{'directory'},
'boot_directory' => $in{'use_boot_directory'} ? $in{'boot_directory'} : '',
'bootloader_id' => $in{'bootloader_id'},
'recheck' => $in{'recheck'} ? 1 : 0,
'removable' => $in{'removable'} ? 1 : 0,
'no_nvram' => $in{'no_nvram'} ? 1 : 0,
'force' => $in{'force'} ? 1 : 0,
);
$in{'confirm'} || &error($text{'install_econfirm'});
&grub2_command('install_cmd') || &error($text{'install_ecmd'});
# Validate all paths and identifiers before any progress output is started.
my $precheck = &grub2_validate_install_options(\%opts);
&error($precheck) if ($precheck);
my ($pre_open, $current_step, $failed_printed, $captured_output) =
(0, '', 0, '');
&ui_print_unbuffered_header(undef, $text{'install_progress_title'}, "");
my $callback = sub {
my ($event, $value) = @_;
if ($event eq 'command') {
# The first event opens the visible command transcript.
$current_step = 'command';
&print_step_start($text{'install_installing'});
print &ui_tag_start('pre', { 'style' => 'margin-left: 10px;' });
$pre_open = 1;
print &html_escape($value)."\n";
return;
}
if ($event eq 'output') {
# Some commands emit output before command_done; keep one pre open.
if (!$pre_open) {
print &ui_tag_start('pre',
{ 'style' => 'margin-left: 10px;' });
$pre_open = 1;
}
$captured_output .= $value;
print &html_escape($value);
return;
}
if ($event eq 'command_done') {
# Close the transcript before printing the final status marker.
&close_output(\$pre_open);
&print_step_done(\$current_step);
return;
}
if ($event eq 'command_failed') {
# Print only one failure line even if the caller also returns an error.
&close_output(\$pre_open);
&print_step_failed(\$current_step, \$failed_printed);
return;
}
};
my $err = &grub2_install_bootloader(\%opts, $callback);
&close_output(\$pre_open);
if ($err) {
# Avoid duplicating the same error when it was already in command output.
&print_step_failed(\$current_step, \$failed_printed)
if ($current_step);
my $shown = $captured_output || '';
$shown =~ s/^\s+|\s+\z//g;
print &ui_tag('pre', &html_escape($err),
{ 'style' => 'margin-left: 10px;' })
if ($err ne $shown);
}
else {
&webmin_log("install", undef, &grub2_install_log_target(\%opts));
}
&ui_print_footer("index.cgi", $text{'install_return'});
# close_output(&open-flag)
# Closes the command output block when it is currently being printed.
sub close_output
{
my ($open) = @_;
if ($$open) {
print &ui_tag_end('pre');
$$open = 0;
}
return;
}
# print_step_start(text)
# Prints the first progress line for the installation step.
sub print_step_start
{
my ($msg) = @_;
print &ui_tag('span', &html_escape($msg." .."),
{ 'data-first-print' => undef });
print "<br>\n";
return;
}
# print_step_done(&current-step)
# Prints a successful progress line and clears the active step.
sub print_step_done
{
my ($current) = @_;
print &ui_tag('span', &html_escape(".. ".$text{'install_done'}),
{ 'data-second-print' => undef });
print "<br><div data-x-br=\"\"></div>\n";
$$current = '';
return;
}
# print_step_failed(&current-step, &printed-flag)
# Prints a failed progress line once and clears the active step.
sub print_step_failed
{
my ($current, $printed) = @_;
return if ($$printed);
print &ui_tag('span', &html_escape(".. ".$text{'install_failed_status'}),
{ 'data-second-print' => undef });
print "<br><div data-x-br=\"\"></div>\n";
$$current = '';
$$printed = 1;
return;
}