) {
if (/^(\S+)\s+(\S+)\s+(\S.*)/) {
push(@rv, "$2 $3");
}
}
close(OUT);
return @rv;
}
}
# install_options(file, package)
# Outputs HTML for choosing install options
sub install_options
{
print &ui_table_row(&hlink($text{'pkgadd_root'}, "root"),
&ui_textbox("root", "/", 50)." ".
&file_chooser_button("root", 1), 3);
}
# install_package(file, package)
# Installs the package in the given file, with options from %in
sub install_package
{
local(@opts, %seen, $wf, $rv, $old_input);
local $real = &translate_filename($_[0]);
local $qm = quotemeta($_[0]);
local $in = $_[2] ? $_[2] : \%in;
local $has_postinstall = 0; #detect if contains postinstall script
if ($in->{'root'} =~ /^\/.+/) {
if (!(-d $in->{'root'})) { &error(&text('pkgadd_eroot', $in->{'root'})); }
push(@opts, "-R", $in->{'root'});
}
if ($in->{'adminfile'} ne '') {
push(@opts, "-a", $in->{'adminfile'});
}
if (-d $real && !-r "$real/pkgproto") {
# Install one package from a file in this directory
local $f;
opendir(DIR, $real);
while($f = readdir(DIR)) {
if (&is_package("$_[0]/$f")) {
local @pkg = &file_packages("$_[0]/$f");
foreach $pkg (@pkg) {
local ($name, $desc) = split(/\s+/, $pkg);
if ($name eq $_[1]) {
return &install_package("$_[0]/$f", $name);
}
}
}
}
closedir(DIR);
return "Failed to find package $_[1]";
}
elsif ($real =~ /\?|\*/) {
# Install one package from a file that matches a glob
local $f;
foreach $f (glob($real)) {
if (&is_package($f)) {
local @pkg = &file_packages($f);
foreach $pkg (@pkg) {
local ($name, $desc) = split(/\s+/, $pkg);
if ($name eq $_[1]) {
return &install_package($f, $name);
}
}
}
}
return "Failed to find package $_[1]";
}
else {
# Install just one package
local ($ph, $ppid) = &foreign_call("proc", "pty_process_exec_logged",
"pkgadd -d $_[0] ".join(" ",@opts)." $_[1]");
while(1) {
$wf = &wait_for($ph, '(.*) \[\S+\]',
'(This package contains scripts|Executing checkinstall script)',
'Installation of .* failed',
'Installation of .* was successful',
'No changes were made to the system',
'\n\/.*\n');
if ($wf == 0) {
# some question which should not have appeared before
if ($seen{$matches[1]}++ > 3) {
$rv = "$old_input$wait_for_input
";
last;
}
&sysprint($ph, "y\n");
}
elsif ($wf == 1) {
# This package contains scripts requiring output to
# be sent to /dev/null. Abort & redo.
$rv = undef;
$has_postinstall = 1;
&sysprint($ph, "n\n");
#let the next elsif catch that 'no changes were made'
#to complete the pkgadd execution.
}
elsif ($wf == 2 || $wf == 4 || $wf == -1) {
# failed for some reason.. give up
$rv = "$old_input$wait_for_input
";
last;
}
elsif ($wf == 3) {
# done ok!
$rv = undef;
last;
}
$old_input = $wait_for_input;
}
close($ph);
if ($has_postinstall) {
# Handle case where pkg has scripts that cause pkgadd to open
# /dev/tty
my $ret = system_logged("pkgadd -n -a pkgadd-no-ask -d $_[0] ".
join(" ",@opts).
" $_[1] 2>&1 > /dev/null")/256;
#only exit values of 1 & 3 are errors (see pkgadd(1M))
$rv = ($ret == 1 || $ret == 3)? "pkgadd returned $ret" : undef;
}
return $rv;
}
}
# check_files(package)
# Fills in the %files array with information about the files belonging
# to some package. Values in %files are path type user group mode size error
sub check_files
{
local($i, %errs, $curr, $line, %file);
undef(%files);
local $qm = quotemeta($_[0]);
$chk = &backquote_command("pkgchk -n $qm 2>&1", 1);
while($chk =~ /^(\S+): (\S+)\n((\s+.*\n)+)([\0-\177]*)$/) {
if ($1 eq "ERROR") { $errs{$2} = $3; }
$chk = $5;
}
&open_execute_command(CHK, "pkgchk -l $qm 2>&1", 1, 1);
FILES: for($i=0; 1; $i++) {
# read one package
$curr = "";
while(1) {
if (!($line = )) { last FILES; }
if ($line =~ /Current status/) { $line = ; last; }
$curr .= $line;
}
# extract information
&parse_pkgchk($curr);
foreach $k (keys %file) { $files{$i,$k} = $file{$k}; }
$files{$i,'error'} = $errs{$files{$i,'path'}};
}
close(CHK);
return $i;
}
# installed_file(file)
# Given a filename, fills %file with details of the given file and returns 1.
# If the file is not known to the package system, returns 0
# Usable values in %file are path type user group mode size packages
sub installed_file
{
local $temp = &transname();
&open_tempfile(TEMP, ">$temp", 0, 1, 1);
print TEMP "$_[0]\n";
close(TEMP);
$out = &backquote_command("pkgchk -l -i $temp 2>&1", 1);
&unlink_file($temp);
if ($out =~ /\S/) {
&parse_pkgchk($out);
return 1;
}
else { return 0; }
}
# delete_package(package)
# Totally remove some package
sub delete_package
{
local($ph, $pth, $ppid, $wf, %seen, $old_input);
local ($ph, $ppid) = &foreign_call("proc", "pty_process_exec_logged",
"pkgrm $_[0]");
if (&wait_for($ph, 'remove this package', 'ERROR')) {
return "package does not exist";
}
&sysprint($ph, "y\n");
while(1) {
$wf = &wait_for($ph, '(.*) \[\S+\]',
'Removal of \S+ failed',
'Removal of \S+ was successful',
'\n\/.*\n');
if ($wf == 0) {
# some question which should not have appeared before
if ($seen{$matches[1]}++) {
$rv = "$old_input$wait_for_input
";
last;
}
&sysprint($ph, "y\n");
}
elsif ($wf == 1) {
# failed for some reason.. give up
$rv = "$old_input$wait_for_input
";
last;
}
elsif ($wf == 2) {
# done ok!
$rv = undef;
last;
}
$old_input = $wait_for_input;
}
close($ph);
return $rv;
}
# parse_pkgchk(output)
# Parse output about one file from pkgchk into the array %file
sub parse_pkgchk
{
undef(%file);
if ($_[0] =~ /Pathname:\s+(.*)/) { $file{'path'} = $1; }
if ($_[0] =~ /Type:\s+(.*)/) {
$file{'type'} = $1 eq "regular file" ? 0 :
$1 eq "directory" ? 1 :
$1 eq "special file" ? 2 :
$1 eq "symbolic link" ? 3 :
$1 eq "linked file" ? 4 :
$1 eq "volatile file" ? 5 :
$1 eq "editted file" ? 5 :
$1 eq "edited file" ? 5 :
-1;
}
if ($_[0] =~ /Source of link:\s+(\S+)/) { $file{'link'} = $1; }
if ($_[0] =~ /Expected owner:\s+(\S+)/) { $file{'user'} = $1; }
if ($_[0] =~ /Expected group:\s+(\S+)/) { $file{'group'} = $1; }
if ($_[0] =~ /Expected mode:\s+(\S+)/) { $file{'mode'} = $1; }
if ($_[0] =~ /size \(bytes\):\s+(\d+)/) { $file{'size'} = $1; }
if ($_[0] =~ /following packages:\n(((\s+.*\n)|\n)+)/)
{ $file{'packages'} = join(' ', grep { $_ ne '' } split(/\s+/, $1)); }
}
sub package_system
{
return $text{'pkgadd_manager'};
}
sub package_help
{
return "pkgadd pkginfo pkgchk pkgrm";
}
1;