chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:12:17 +08:00
commit cf8edb9f21
44281 changed files with 1655134 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
---- Changes since 2.641 ----
Fix Alpine Linux mysql/mariadb package installs names due missing server utils (means at least Alpine Linux package installation is supported since Alpine linux v 3.16 up to edge)
---- Changes since 1.130 ----
Packages can now be installed directly from yum, if installed.
The entire system can also be upgraded from yum.
---- Changes since 1.150 ----
The package update system (YUM, APT or Redhat Network) can now be selected on the Module Config page, rather than being always detected automatically.
---- Changes since 1.170 ----
Added support for the Blastwave contributed Solaris package management installed, pkg-get.
---- Changes since 1.180 ----
On Solaris systems, packages can now be installed from a directory or local filesystem wildcard.
---- Changes since 1.220 ----
Added support for the Mandrake URPMI package system.
Cleaned up package system support code, to allow searching for packages in a consistent way on all operating systems.
---- Changes since 1.230 ----
Added an option to enable disabled repositories when installing a package from YUM.
---- Changes since 1.290 ----
Added basic support for MSI packages on Windows systems.
---- Changes since 1.300 ----
Added a Module Config option to use aptitude instead of apt-get on Debian-based systems.
---- Changes since 1.310 ----
Added a popup progress window to track uploaded package files.
---- Changes since 1.330 ----
Fixed several bugs related to finding available updates on Debian and Redhat.
Added detection of epochs for RPMs and packages from YUM.
---- Changes since 1.340 ----
Added an Upgrade All button for CSW packages.
---- Changes since 1.440 ----
Added a Module Config option to not use any update system, even if YUM or APT are installed.
Added the function package_files for other modules to call, when only a list of files in some package is needed.
The selected package and update systems are now checked when the module is opened, and an error message displayed if any needed commands are missing.
---- Changes since 1.470 ----
On Solaris, added support for the pkgutil command from Blastwave for installing packages, which replaces the old pkg-get.
On Solaris, package versions are now shown in the package list and tree.
---- Changes since 1.500 ----
Fixed several bugs related to YUM available package updates.
Added the update_system_updates function to more efficiently find available packages for YUM and APT.
---- Changes since 1.530 ----
Debian packages marked as "hold" are no longer offered as possible updates. This is visible in the Software Package Updates module.
---- Changes since 1.620 ----
Added support for updating and installing packages from FreeBSD ports.
---- Changes since 1.700 ----
Added support for the FreeBSD pkgng binary package repository as an alternative to ports.
---- Changes since 1.740 ----
MacOS systems with PKGsrc installed can now use this module to manage and install binary packages.
---- Changes since 1.890 ----
When installing a package, the list of other dependencies that will be also installed is displayed for confirmation.
+574
View File
@@ -0,0 +1,574 @@
# aix-lib.pl
# Functions for aix package management
sub list_package_system_commands
{
return ("lslpp", "geninstall", "installp");
}
# list_packages([package]*)
# Fills the array %packages with a list of all packages
sub list_packages
{
local($_, $list, $i, $file, %fileset);
$i = 0;
$list = join(' ', map { quotemeta($_) } @_);
%packages = ( );
&open_execute_command(LSLPP, "lslpp -L -c $list 2>&1 | grep -v '#'", 1, 1);
while($file = <LSLPP>) {
%fileset = &fileset_info($file);
if ($fileset{"type"} eq "R") {
$packages{$i,'name'} = join("-", $fileset{"package_name"}, $fileset{"level"});
$packages{$i,'class'} = $fileset{"package_name"};
$packages{$i,'desc'} = $fileset{"description"};
}
else {
$packages{$i,'name'} = $fileset{"fileset"};
$packages{$i,'class'} = $fileset{"class"};
$packages{$i,'desc'} = $fileset{"description"};
}
$i++;
}
close(LSLPP);
return $i;
}
# package_info(package)
# Returns an array of package information in the order
# name, class, description, arch, version, vendor, installtime
sub package_info
{
local(@rv, @tmp, $d, $out, $archout, %fileset);
local $qm = quotemeta($_[0]);
$out = &backquote_command("lslpp -L -c $qm 2>&1 | grep -v '#'", 1);
%fileset = &fileset_info($out);
if ($out =~ /^lslpp:/) {
&open_execute_command(RPM, "rpm -q $qm --queryformat \"%{NAME}-%{VERSION}\\n%{GROUP}\\n%{ARCH}\\n%{VERSION}\\n%{VENDOR}\\n%{INSTALLTIME}\\n\" 2>/dev/null", 1, 1);
@tmp = <RPM>;
chop(@tmp);
if (!@tmp) { return (); }
close(RPM);
&open_execute_command(RPM, "rpm -q $qm --queryformat \"%{DESCRIPTION}\"", 1, 1);
while(<RPM>) { $d .= $_; }
close(RPM);
return ($tmp[0], $tmp[1], $d, $tmp[2], $tmp[3], $tmp[4], &make_date($tmp[5]));
}
else {
$archout = `uname -s`;
push(@rv, $_[0]);
push(@rv, $fileset{"class"});
push(@rv, $fileset{"description"});
push(@rv, $archout);
push(@rv, $fileset{"level"});
push(@rv, $text{'aix_unknown'});
push(@rv, $text{'aix_unknown'});
return @rv;
}
}
# virtual_package_info(package)
# Returns an array of package information for a virtual package, usually called
# if "package_info" returns nothing.
sub virtual_package_info
{
return ( );
}
# is_package(file)
# Tests if some file is a valid package file
sub is_package
{
local($out, $name, $filetype);
local $qm = quotemeta($_[0]);
$out = &backquote_command("file $qm 2>&1", 1);
($name, $filetype) = split(/:/, $out);
if ($filetype =~ /backup\/restore format file/i) {
$fileset{"filetype"} = "AIX";
return 1;
}
elsif ($filetype =~ /RPM v3 bin PowerPC/i) {
$fileset{"filetype"} = "RPM";
return 1;
}
else { return 0; }
}
# file_packages(file)
# Returns a list of all packages in the given file, in the form
# package description
sub file_packages
{
local($_, $line, $i, $j, $file, $out, $continue, @token, $firstline);
local(@rv, @output, $description, @vrmf, @field, $k, $l, $stub);
local $qm = quotemeta($_[0]);
local $real = &translate_filename($_[0]);
if (&is_package($_[0])) {
@token = split(/\//, $_[0]);
$i = @token;
$file = $token[$i - 1];
if ($fileset{"filetype"} eq "RPM") {
$fileset{"fileset_name"} = "R:$file";
if (-d $real) {
local @rv;
&open_execute_file(RPM, "cd $qm ; rpm -q -p *.rpm --queryformat \"%{NAME}-%{VERSION} %{SUMMARY}\\n\" 2>&1", 1, 1);
while(<RPM>) {
chop;
push(@rv, $_) if (!/does not appear|query of.*failed/);
}
close(RPM);
return @rv;
}
else {
local($out);
$out = &backquote_command("rpm -q -p $qm --queryformat \"%{NAME}-%{VERSION} %{SUMMARY}\" 2>&1", 1);
return ($out);
}
}
elsif ($fileset{"filetype"} eq "AIX") {
&open_tempfile(FILE, $_[0]);
$line = <FILE>;
$continue = 1;
while ($continue) {
if ($line =~ /^\}/) { $continue = 0; }
elsif (($line =~ /lpp_name/) && ($line =~ / \{/)) {
$firstline = $line;
$line = <FILE>;
$out = $out . $line;
}
elsif ($line =~ /^\]/) {
$line = <FILE>;
if ($line =~ /^\}/) { $continue = 0; }
else { $out = $out . $line; }
}
$line = <FILE>;
}
close(FILE);
@field = split(/\s/, $firstline);
$j = @field;
for ($i = 0; $i < $j; $i++) {
if ($field[$i] =~ /\{/) {
$fileset{"fileset_name"} = $field[$i - 1] =~ /\>|\s+/ ? $file :
$field[$i - 1];
}
}
@output = split(/\n/, $out);
$j = @output;
for ($i = 0; $i < $j; $i++) {
if ($output[$i] !~ /\{|\}|\*/) {
@field = split(/\s/, $output[$i]);
$out = undef;
$out = "$fileset{fileset_name} ";
$description = undef;
@vrmf = split(/\./, $field[1]);
$vrmf[0] =~ s/^0+//;
$vrmf[1] =~ s/^0+//; if ($vrmf[1] == "") { $vrmf[1] = "0"; }
$vrmf[2] =~ s/^0+//; if ($vrmf[2] == "") { $vrmf[2] = "0"; }
$vrmf[3] =~ s/^0+//; if ($vrmf[3] == "") { $vrmf[3] = "0"; }
if ($vrmf[0] != "") {
$k = @field;
for ($l = 6; $l <= $k; $l++) {
$description = $description . " " . $field[$l];
}
$out = $out . "$field[0], $vrmf[0].$vrmf[1].$vrmf[2].$vrmf[3], $description";
}
}
push(@rv, $out);
}
return @rv;
}
}
else { return undef; }
}
# install_options(file, package)
# Outputs HTML for choosing install options
sub install_options
{
local(@token, $command, $i, $j, $file, $directory);
@token = split(/\//, $_[0]);
$i = @token;
for ( $j = 1; $j < $i - 1; $j++) {
$directory = join("/", $directory, $token[$j]);
}
$file = $token[$i-1];
print "<script language=\"JavaScript\">\n";
print " function changeRadio(formName, radiobutton, disable) {\n";
print " for( var i=0; i<formName.elements.length; i++) {\n";
print " if (formName.elements[i].name == radiobutton) {\n";
print " formName.elements[i].checked = disable;\n";
print " }\n";
print " }\n";
print " }\n";
print "</script>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_device'}</b>", "aix_device"), "</td>\n";
print "<td>$directory</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_software'}</b>", "aix_software"), "</td>\n";
print "<td>$file</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_preview'}</b>", "aix_preview"), "</td>\n";
print "<td><input type=radio name=preview value=1> $text{'yes'}\n";
print "<input type=radio name=preview value=0 checked> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_commit'}</b>", "aix_commit"), "</td>\n";
print "<td><input type=radio name=commit value=1 checked> $text{'yes'}\n";
print "<input type=radio name=commit value=0 \n";
print " onClick=\"changeRadio(this.form, 'save', true)\"> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_save'}</b>", "aix_save"), "</td>\n";
print "<td><input type=radio name=save value=1> $text{'yes'}\n";
print "<input type=radio name=save value=0 checked> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_auto'}</b>", "aix_auto"), "</td>\n";
print "<td><input type=radio name=auto value=1 \n";
print " onClick=\"changeRadio(this.form, 'overwrite', false)\" checked> $text{'yes'}\n";
print "<input type=radio name=auto value=0> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_extend'}</b>", "aix_extend"), "</td>\n";
print "<td><input type=radio name=extend value=1 checked> $text{'yes'}\n";
print "<input type=radio name=extend value=0> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_overwrite'}</b>", "aix_overwrite"), "</td>\n";
print "<td><input type=radio name=overwrite value=1 \n";
print " onClick=\"changeRadio(this.form, 'auto', false)\"> $text{'yes'}\n";
print "<input type=radio name=overwrite value=0 checked > $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_verify'}</b>", "aix_verify"), "</td>\n";
print "<td><input type=radio name=verify value=1> $text{'yes'}\n";
print "<input type=radio name=verify value=0 checked> $text{'no'}</td>\n";
print "</tr>\n";
# print "<tr>\n";
# print "<td>", &hlink("<b>$text{'aix_include'}</b>", "aix_include"), "</td>\n";
# print "<td><input type=radio name=include value=1> $text{'yes'}\n";
# print "<input type=radio name=include value=0 checked> $text{'no'}</td>\n";
# print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_detail'}</b>", "aix_detail"), "</td>\n";
print "<td><input type=radio name=detail value=1> $text{'yes'}\n";
print "<input type=radio name=detail value=0 checked> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_process'}</b>", "aix_process"), "</td>\n";
print "<td><input type=radio name=process value=1 checked> $text{'yes'}\n";
print "<input type=radio name=process value=0> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_accept'}</b>", "aix_accept"), "</td>\n";
print "<td><input type=radio name=accept value=1> $text{'yes'}\n";
print "<input type=radio name=accept value=0 checked> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_license'}</b>", "aix_license"), "</td>\n";
print "<td><input type=radio name=license value=1> $text{'yes'}\n";
print "<input type=radio name=license value=0 checked> $text{'no'}</td>\n";
print "</tr>\n";
print "<tr>\n";
print "<td>", &hlink("<b>$text{'aix_clean'}</b>", "aix_clean"), "</td>\n";
print "<td><input type=radio name=clean value=1 \n";
print " onClick=\"changeRadio(this.form, 'preview', false),\n";
print " changeRadio(this.form, 'commit', false),\n";
print " changeRadio(this.form, 'save', false),\n";
print " changeRadio(this.form, 'auto', false),\n";
print " changeRadio(this.form, 'extend', false),\n";
print " changeRadio(this.form, 'overwrite', false),\n";
print " changeRadio(this.form, 'verify', false),\n";
# print " changeRadio(this.form, 'include', false),\n";
print " changeRadio(this.form, 'detail', false),\n";
print " changeRadio(this.form, 'process', false),\n";
print " changeRadio(this.form, 'accept', false),\n";
print " changeRadio(this.form, 'license', false)\"> $text{'yes'}\n";
print "<input type=radio name=clean value=0\n";
print " onClick=\"reset()\" checked> $text{'no'}</td>\n";
print "</tr>\n";
}
# install_package(file, package)
# Installs the package in the given file, with options from %in
sub install_package
{
local(@token, $command, $directory, $out);
local($qdir, $qset, $qargs);
@token = split(/\//, $_[0]);
$i = @token;
for ( $j = 1; $j < $i - 1; $j++) {
$directory = join("/", $directory, $token[$j]);
}
local $args = ($in{"preview"} ? "p" : "") .
($in{"commit"} ? "c" : "") .
($in{"save"} ? "" : "N") .
($in{"auto"} ? "g" : "") .
($in{"extend"} ? "X" : "") .
($in{"overwrite"} ? "F" : "") .
($in{"verify"} ? "v" : "") .
# ($in{"include"} ? "G" : "") .
($in{"detail"} ? "V2" : "") .
($in{"process"} ? "" : "S") .
($in{"accept"} ? "Y" : "") .
($in{"license"} ? "E" : "");
$qargs = quotemeta("-a$args");
$qdir = quotemeta($directory);
$qset = quotemeta($fileset{fileset_name});
$command = "geninstall -I $qargs -d $qdir $qset 2>&1";
if ($in{"clean"}) {
$args = "-C";
$command = "installp $args 2>&1";
}
local $out = &backquote_logged($command);
if (($?) || ($in{"preview"}) || ($in{"clean"})) {
return "<pre>$command<br>$out</pre>";
}
return undef;
}
# 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 link
sub check_files
{
local($_, $list, $i, $_, @w, %errs, %myfile, $epath, $path, $fileset, $file);
local $qm = quotemeta($_[0]);
$i = 0;
$list = join(' ', @_);
&open_execute_command(LSLPP, "lslpp -f -c $qm 2>&1 | grep -v '#'", 1, 1);
$out = <LSLPP>;
if ($out =~ /lslpp:/) {
&open_execute_command(RPM, "rpm -V $qm", 1, 1);
while(<RPM>) {
/^(.{8}) (.) (.*)$/;
if ($1 eq "missing ") { $errs{$3} = "Missing"; }
else {
$epath = $3;
@w = grep { $_ ne "." } split(//, $1);
$errs{$epath} =
join("\n", map { "Failed $etype{$_} check" } @w);
}
}
close(RPM);
&open_execute_command(RPM, "rpm -q $qm -l --dump", 1, 1);
while(<RPM>) {
chop;
if ($_ =~ /(contains no files)/) { return $i; }
@w = split(/ /);
$files{$i,'path'} = $w[0];
if ($w[10] ne "X") { $files{$i,'link'} = $w[10]; }
$files{$i,'type'} = $w[10] ne "X" ? 3 :
(-d &translate_filename($w[0]))? 1 :
$w[7] ? 5 : 0;
$files{$i,'user'} = $w[5];
$files{$i,'group'} = $w[6];
$files{$i,'size'} = $w[1];
$files{$i,'error'} = $w[7] ? "" : $errs{$w[0]};
$i++;
}
close(RPM);
}
else {
while($fileinfo = <LSLPP>) {
chop($fileinfo);
#Path:Fileset:File
($path, $fileset, $file) = split(/:/, $fileinfo);
%myfile = &file_info($file);
$files{$i,'path'} = $myfile{"path"};
$files{$i,'type'} = $myfile{"type"};
$files{$i,'user'} = $myfile{"uid"};
$files{$i,'group'} = $myfile{"gid"};
$files{$i,'mode'} = $myfile{"mode"};
$files{$i,'size'} = $myfile{"size"};
$files{$i,'link'} = $myfile{"link"};
$files{$i,'error'} = $myfile{"err"};
$i++;
}
}
close(LSLPP);
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(%myfile);
local $qm = quotemeta($_[0]);
$out = &backquote_command("lslpp -wc $qm 2>&1 | grep -v '#'", 1);
if ($?) {
local($pkg, @w, $_);
undef(%file);
$pkg = &backquote_command("rpm -q -f $qm --queryformat \"%{NAME}-%{VERSION}\\n\" 2>&1", 1);
if ($pkg =~ /not owned/ || $?) { return 0; }
@pkgs = split(/\n/, $pkg);
&open_execute_command(RPM, "rpm -q $pkgs[0] -l --dump", 1);
while(<RPM>) {
chop;
@w = split(/ /);
if ($w[0] eq $_[0]) {
$file{'packages'} = join(' ', @pkgs);
$file{'path'} = $w[0];
if ($w[10] ne "X") { $files{$i,'link'} = $w[10]; }
$file{'type'} = $w[10] ne "X" ? 3 :
(-d &translate_filename($w[0])) ? 1 :
$w[7] ? 5 : 0;
$file{'user'} = $w[5];
$file{'group'}= $w[6];
$file{'mode'} = substr($w[4], -4);
$file{'size'} = $w[1];
last;
}
}
close(RPM);
}
else {
%myfile = &file_info($_[0]);
$file{'path'} = $myfile{"path"};
$file{'type'} = $myfile{"type"};
$file{'user'} = $myfile{"uid"};
$file{'group'} = $myfile{"gid"};
$file{'mode'} = $myfile{"mode"};
$file{'size'} = $myfile{"size"};
$file{'link'} = $myfile{"link"};
$file{'packages'} = $myfile{"package"};
}
return 1;
}
# delete_package(package)
# Totally remove some package
sub delete_package
{
local(%fileset, $file, $out, $rv);
local $temp = &transname();
local $qm = quotemeta($_[0]);
$file = &backquote_command("lslpp -L -c $qm 2>&1 | grep -v '#'", 1);
%fileset = &fileset_info($file);
$rv = &system_logged("geninstall -u ".quotemeta($_[0])." >".
quotemeta($temp)." 2>&1");
local $out = &backquote_command("cat ".quotemeta($temp));
&unlink_file($temp);
if ($rv) { return "<pre>$out</pre>"; }
return undef;
}
sub fileset_info
{
local($_, $out, %fileset, $package_name, $fileset, $level, $state, $ptf_id,
$fix_state, $type, $description, $destination_dir, $uninstaller,
$msg_cat, $msg_set, $msg_num, $parent, $class);
%fileset = ();
($package_name, $fileset, $level, $state, $ptf_id, $fix_state,
$type, $description, $destination_dir, $uninstaller, $msg_cat,
$msg_set, $msg_num, $parent) = split(/:/, $_[0]);
($class, $stub) = split(/\./, $package_name);
$fileset{"class"} = $class;
$fileset{"package_name"} = $package_name;
$fileset{"fileset"} = $fileset;
$fileset{"level"} = $level;
$fileset{"state"} = $state;
$fileset{"ptf_id"} = $ptf_id;
$fileset{"fix_state"} = $fix_state;
$fileset{"type"} = $type;
$fileset{"description"} = $description;
$fileset{"destination_dir"} = $destination_dir;
$fileset{"uninstaller"} = $uninstaller;
$fileset{"msg_cat"} = $msg_cat;
$fileset{"msg_set"} = $msg_set;
$fileset{"msg_num"} = $msg_num;
$fileset{"parent"} = $parent;
return(%fileset);
}
sub file_info
{
local($_, %file, @out, $filename, $fileset, $type,
$dev, $ino, $mode, $nlink, $uid, $gid, @args, $rdev,
$size, $atime, $mtime, $ctime, $blksize, $blocks);
%file = ();
local $real;
if ($_[0] =~ /->/) {
($filename, $symlink) = split(/->/, $_[0]);
$real = &translate_filename($filename);
chop($filename);
($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks) = lstat($real);
}
else {
$filename = $_[0];
$real = &translate_filename($filename);
($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks) = stat($real);
}
local $qm = quotemeta($filename);
@out = &backquote_command("lslpp -wc $qm 2>&1", 1);
($stub, $fileset, $type) = split(/:/, $out[1]);
$file{"path"} = $filename;
$file{"dev"} = sprintf "%d,%d", $dev/256, $dev%256;
$file{"ino"} = $ino;
$file{"mode"} = sprintf "%o", $mode & 07777;
$file{"nlink"} = $nlink;
$file{"uid"} = getpwuid($uid);
$file{"gid"} = getgrgid($gid);
$file{"rdev"} = readlink($rdev);
$file{"size"} = $size ? $size : 0;
$file{"atime"} = scalar(localtime($atime));
$file{"mtime"} = scalar(localtime($mtime));
$file{"ctime"} = scalar(localtime($ctime));
$file{"blksize"} = $blksize;
$file{"blocks"} = $blocks;
$file{"link"} = readlink($real);
$file{"package"} = $fileset;
$file{"err"} = -e $real ? 0 : "Error";
$file{"type"} = -l $real ? 3 :
-d $real ? 1 :
0;
return(%file);
}
sub package_system
{
return $text{'aix_manager'};
}
sub package_help
{
return "installp lslpp";
}
1;
+378
View File
@@ -0,0 +1,378 @@
# apk-lib.pl
# Functions for Alpine Package Keeper package management
$ENV{'PATH'} .= ":/sbin:/usr/sbin";
$apk_installed_db = "/lib/apk/db/installed";
sub list_package_system_commands
{
return ("apk");
}
sub list_update_system_commands
{
return ("apk");
}
# parse_apk_installed()
# Returns installed packages from APK's package database
sub parse_apk_installed
{
my @rv;
my $pkg = { };
my $last;
open(my $db, "<", $apk_installed_db) || return ();
while(my $line = <$db>) {
$line =~ s/\r?\n$//;
if ($line eq "") {
push(@rv, $pkg) if ($pkg->{'P'});
$pkg = { };
$last = undef;
next;
}
if ($line =~ /^([A-Za-z]):(.*)$/) {
$pkg->{$1} = $2;
$last = $1;
}
elsif ($line =~ /^\t(.*)$/ && defined($last)) {
$pkg->{$last} .= "\n".$1;
}
}
close($db);
push(@rv, $pkg) if ($pkg->{'P'});
return @rv;
}
sub apk_package_class
{
return lc($_[0]) =~ /^[a-e]/ ? "A-E" :
lc($_[0]) =~ /^[f-j]/ ? "F-J" :
lc($_[0]) =~ /^[k-o]/ ? "K-O" :
lc($_[0]) =~ /^[p-t]/ ? "P-T" :
lc($_[0]) =~ /^[u-z]/ ? "U-Z" : "Other";
}
sub split_apk_name_version
{
my ($nv) = @_;
return ($1, $2) if ($nv =~ /^(.+)-([0-9][^\s]*)$/);
return ($nv, undef);
}
sub apk_package_record
{
my ($name, $ver) = @_;
foreach my $p (&parse_apk_installed()) {
next if ($p->{'P'} ne $name);
next if ($ver && $p->{'V'} ne $ver);
return $p;
}
return undef;
}
sub apk_quote_packages
{
return join(" ", map { quotemeta($_) } split(/\s+/, $_[0]));
}
# list_packages([package]*)
# Fills the array %packages with a list of all packages
sub list_packages
{
my %wanted = map { $_ => 1 } @_;
my $i = 0;
%packages = ( );
foreach my $p (sort { $a->{'P'} cmp $b->{'P'} } &parse_apk_installed()) {
next if (@_ && !$wanted{$p->{'P'}});
$packages{$i,'name'} = $p->{'P'};
$packages{$i,'class'} = &apk_package_class($p->{'P'});
$packages{$i,'version'} = $p->{'V'};
$packages{$i,'desc'} = $p->{'T'};
$packages{$i,'arch'} = $p->{'A'};
$packages{$i,'url'} = $p->{'U'};
$i++;
}
return $i;
}
# package_search(string)
# Searches installed packages by name and description
sub package_search
{
my ($search) = @_;
my $n = &list_packages();
my $i = 0;
my %old = %packages;
%packages = ( );
for(my $j=0; $j<$n; $j++) {
if ($old{$j,'name'} =~ /\Q$search\E/i ||
$old{$j,'desc'} =~ /\Q$search\E/i) {
foreach my $k ('name', 'class', 'version', 'desc', 'arch',
'url') {
$packages{$i,$k} = $old{$j,$k};
}
$i++;
}
}
return $i;
}
# package_info(package, [version])
# Returns name, class, description, arch, version, vendor, installtime, url
sub package_info
{
my ($name, $ver) = @_;
my $p = &apk_package_record($name, $ver);
return ( ) if (!$p);
return ( $p->{'P'}, &apk_package_class($p->{'P'}),
$p->{'T'} || $text{'apk_unknown'},
$p->{'A'} || $text{'apk_unknown'},
$p->{'V'} || $text{'apk_unknown'},
$p->{'m'} || "Alpine Linux",
undef,
$p->{'U'} );
}
sub virtual_package_info
{
return ( );
}
# package_files(package)
# Returns a list of all files in some package
sub package_files
{
my ($name) = @_;
my $qname = quotemeta($name);
my @rv;
&open_execute_command(PKGINFO, "apk info -L $qname 2>/dev/null", 1, 1);
while(<PKGINFO>) {
s/\r|\n//g;
next if (!$_ || / contains:$/);
$_ = "/".$_ if ($_ !~ /^\//);
push(@rv, $_);
}
close(PKGINFO);
return @rv;
}
# check_files(package)
# Fills in the %files array with information about files belonging to a package
sub check_files
{
my ($name) = @_;
my @pkgfiles = &package_files($name);
%files = ( );
for(my $i=0; $i<@pkgfiles; $i++) {
my $path = $pkgfiles[$i];
my $real = &translate_filename($path);
my @st = stat($real);
$files{$i,'path'} = $path;
$files{$i,'type'} = -l $real ? 3 : -d $real ? 1 : 0;
$files{$i,'user'} = @st ? getpwuid($st[4]) : undef;
$files{$i,'group'} = @st ? getgrgid($st[5]) : undef;
$files{$i,'mode'} = @st ? sprintf("%o", $st[2] & 07777) : undef;
$files{$i,'size'} = @st ? $st[7] : 0;
$files{$i,'link'} = readlink($real);
$files{$i,'error'} = "Does not exist" if (!@st);
}
return scalar(@pkgfiles);
}
# installed_file(file)
# Fills %file with details of the package that owns a file
sub installed_file
{
my ($path) = @_;
my $qpath = quotemeta($path);
my $out = &backquote_command("apk info -W $qpath 2>&1", 1);
return 0 if ($? || $out !~ / is owned by (\S+)/);
my ($pkg, $ver) = &split_apk_name_version($1);
my $real = &translate_filename($path);
my @st = stat($real);
%file = ( );
$file{'path'} = $path;
$file{'type'} = -l $real ? 3 : -d $real ? 1 : 0;
$file{'user'} = @st ? getpwuid($st[4]) : undef;
$file{'group'} = @st ? getgrgid($st[5]) : undef;
$file{'mode'} = @st ? sprintf("%o", $st[2] & 07777) : undef;
$file{'size'} = @st ? $st[7] : 0;
$file{'link'} = readlink($real);
$file{'packages'} = $pkg;
$file{'versions'} = $ver;
return 1;
}
# is_package(file)
sub is_package
{
my ($path) = @_;
my $qpath = quotemeta($path);
my $out = &backquote_command("tar -tzf $qpath .PKGINFO 2>/dev/null", 1);
return $? ? 0 : 1;
}
# file_packages(file)
# Returns a list of packages in an apk file, in "package description" form
sub file_packages
{
my ($path) = @_;
my $qpath = quotemeta($path);
my $out = &backquote_command("tar -xOzf $qpath .PKGINFO 2>/dev/null", 1);
return ( ) if ($?);
my %info;
foreach my $line (split(/\r?\n/, $out)) {
if ($line =~ /^(\S+)\s*=\s*(.*)$/) {
$info{$1} = $2;
}
}
return $info{'pkgname'} ? ( $info{'pkgname'}." ".$info{'pkgdesc'} ) : ( );
}
sub install_options
{
print &ui_table_row($text{'apk_untrusted'},
&ui_yesno_radio("untrusted", 0));
}
# install_package(file, package, [&inputs])
sub install_package
{
my ($path, $package, $inref) = @_;
$inref ||= \%in;
my $qpath = quotemeta($path);
my $args = $inref->{'untrusted'} ? "--allow-untrusted " : "";
my $out = &backquote_logged("apk add $args$qpath 2>&1 </dev/null");
return $? ? "<pre>$out</pre>" : undef;
}
# delete_package(package)
sub delete_package
{
my ($name) = @_;
my $out = &backquote_logged("apk del ".quotemeta($name)." 2>&1 </dev/null");
return $? ? "<pre>$out</pre>" : undef;
}
sub package_dependencies
{
my ($name, $ver) = @_;
my $p = &apk_package_record($name, $ver);
return ( ) if (!$p || !$p->{'D'});
my @rv;
foreach my $dep (split(/\s+/, $p->{'D'})) {
next if (!$dep);
$dep =~ s/^\!//;
if ($dep =~ /^([A-Za-z0-9+_.-]+)([<>=~]+)(\S+)$/) {
push(@rv, { 'package' => $1,
'compare' => $2,
'version' => $3 });
}
elsif ($dep =~ /^[A-Za-z0-9+_.-]+$/) {
push(@rv, { 'package' => $dep });
}
else {
push(@rv, { 'other' => $dep });
}
}
return @rv;
}
sub package_system
{
return $text{'apk_manager'};
}
sub package_help
{
return "apk";
}
###### Update system functions
sub update_system_search
{
my ($search) = @_;
my $pattern = defined($search) && $search ne "" && $search ne ".*" ?
"*".$search."*" : "*";
my @rv;
&clean_language();
&open_execute_command(SEARCH, "apk search -v ".quotemeta($pattern)." 2>/dev/null", 1, 1);
while(<SEARCH>) {
s/\r|\n//g;
if (/^(.+)-([0-9][^\s]*)\s+-\s+(.*)$/) {
push(@rv, { 'name' => $1,
'version' => $2,
'desc' => $3 });
}
}
close(SEARCH);
&reset_environment();
return @rv;
}
sub update_system_available
{
&execute_command("apk update");
return &update_system_search(".*");
}
sub update_system_updates
{
my @rv;
&execute_command("apk update");
&clean_language();
&open_execute_command(UPDATES, "apk version -l '<' -v 2>/dev/null", 1, 1);
while(<UPDATES>) {
s/\r|\n//g;
if (/^(.+)-([0-9][^\s]*)\s+<\s+(\S+)/) {
push(@rv, { 'name' => $1,
'oldversion' => $2,
'version' => $3 });
}
}
close(UPDATES);
&reset_environment();
return @rv;
}
sub update_system_install
{
my $update = $_[0] || $in{'update'};
my @rv;
my $qupdate = &apk_quote_packages($update);
my $cmd = "apk add --update --upgrade $qupdate";
print &text('apk_install', "<tt>".&html_escape($cmd)."</tt>"),"\n";
print "<pre data-installer>";
&additional_log('exec', undef, $cmd);
&open_execute_command(CMD, "$cmd 2>&1 </dev/null", 2);
while(<CMD>) {
if (/\b(?:Installing|Upgrading|Downgrading)\s+(\S+)\s+\(/) {
push(@rv, $1);
}
print &html_escape($_);
}
close(CMD);
print "</pre>\n";
if ($?) { print "$text{'apk_failed'}<p>\n"; }
else { print "$text{'apk_ok'}<p>\n"; }
return &unique(@rv);
}
sub update_system_resolve
{
my ($name) = @_;
return $name eq "apache" ? "apache2" :
$name eq "dhcpd" ? "dhcp" :
$name eq "mysql" ? "mariadb mariadb-client mariadb-server-utils" :
$name eq "postgresql" ? "postgresql postgresql-client" :
$name eq "openldap" ? "openldap openldap-clients" :
$name eq "ldap" ? "openldap openldap-clients" :
$name eq "dovecot" ? "dovecot" :
$name eq "samba" ? "samba samba-client" :
$name eq "openssh" ? "openssh" :
$name eq "squid" ? "squid" :
$name;
}
1;
+627
View File
@@ -0,0 +1,627 @@
# apt-lib.pl
# Functions for installing packages from debian APT
$apt_get_command = $config{'apt_mode'} ? "aptitude" : "apt-get";
$apt_search_command = $config{'apt_mode'} ? "aptitude" : "apt-cache";
$sources_list_file = "/etc/apt/sources.list";
$sources_list_dir = "/etc/apt/sources.list.d";
sub list_update_system_commands
{
return ($apt_get_command, $apt_search_command);
}
# strip_apt_package_arch(package)
# Returns an APT package name without any Debian architecture suffix.
sub strip_apt_package_arch
{
my ($name) = @_;
$name =~ s/:[A-Za-z0-9][A-Za-z0-9._-]*$//;
return $name;
}
# update_system_install([package], [&in], [no-force])
# Install some package with apt
sub update_system_install
{
local $update = $_[0] || $in{'update'};
local $force = !$_[2];
local (@rv, @newpacks);
# Build the command to run
$ENV{'UCF_FORCE_CONFFOLD'} = 'YES';
$ENV{'DEBIAN_FRONTEND'} = 'noninteractive';
local $uicmd = "$apt_get_command -y ".($force ? " -f" : "")." install $update";
$update = join(" ", map { quotemeta($_) } split(/\s+/, $update));
local $cmd = "$apt_get_command -y ".($force ? " -f" : "")." install $update";
print &text('apt_install', "<tt>".&html_escape($uicmd)."</tt>"),"\n";
print "<pre data-installer>";
&additional_log('exec', undef, $cmd);
# Run dpkg --configure -a to clear any un-configured packages
$SIG{'TERM'} = 'ignore'; # This may cause a Webmin re-config!
local $out = &backquote_logged("dpkg --configure -a 2>&1 </dev/null");
print &html_escape($out);
# Create an input file of 'yes'
local $yesfile = &transname();
&open_tempfile(YESFILE, ">$yesfile", 0, 1);
foreach (0..100) {
&print_tempfile(YESFILE, "Yes\n");
}
&close_tempfile(YESFILE);
# Run the command
&clean_language();
&open_execute_command(CMD, "$cmd <".quotemeta($yesfile), 2);
while(<CMD>) {
if (/setting\s+up\s+(\S+)/i && !/as\s+MDA/i) {
push(@rv, &strip_apt_package_arch($1));
}
elsif (/packages\s+will\s+be\s+upgraded/i ||
/new\s+packages\s+will\s+be\s+installed/i) {
print;
$line = $_ = <CMD>;
$line =~ s/^\s+//; $line =~ s/\s+$//;
push(@newpacks, split(/\s+/, $line));
}
print &html_escape("$_");
}
close(CMD);
&reset_environment();
if (!@rv && $config{'package_system'} ne 'debian' && !$?) {
# Other systems don't list the packages installed!
@rv = @newpacks;
}
print "</pre>\n";
if ($?) { print "$text{'apt_failed'}<p>\n"; }
else { print "$text{'apt_ok'}<p>\n"; }
return @rv;
}
# update_system_operations(packages)
# Given a list of packages, returns a list containing packages that will
# actually get installed, each of which is a hash ref with name and version.
sub update_system_operations
{
my ($packages) = @_;
$ENV{'UCF_FORCE_CONFFOLD'} = 'YES';
$ENV{'DEBIAN_FRONTEND'} = 'noninteractive';
my $cmd = "apt-get -s install ".
join(" ", map { quotemeta($_) } split(/\s+/, $packages)).
" </dev/null 2>&1";
&clean_language();
my $out = &backquote_command($cmd);
&reset_environment();
my @rv;
foreach my $l (split(/\r?\n/, $out)) {
if ($l =~ /Inst\s+(\S+)\s+\[(\S+)\]\s+\(([^ \)]+)/ ||
$l =~ /Inst\s+(\S+)\s+\[(\S+)\]/) {
# Format like : Inst telnet [amd64] (5.6.7 Ubuntu)
my $pkg = { 'name' => $1,
'version' => $3 || $2 };
if ($pkg->{'version'} =~ s/^(\S+)://) {
$pkg->{'epoch'} = $1;
}
$pkg->{'name'} = &strip_apt_package_arch($pkg->{'name'});
push(@rv, $pkg);
}
elsif ($l =~ /Inst\s+(\S+)\s+\(([^ \)]+)/) {
# Format like : Inst telnet (5.6.7 Ubuntu [amd64])
my $pkg = { 'name' => $1,
'version' => $2 };
if ($pkg->{'version'} =~ s/^(\S+)://) {
$pkg->{'epoch'} = $1;
}
$pkg->{'name'} = &strip_apt_package_arch($pkg->{'name'});
push(@rv, $pkg);
}
}
return @rv;
}
# update_system_form()
# Shows a form for updating all packages on the system
sub update_system_form
{
print &ui_subheading($text{'apt_form'});
print &ui_form_start("apt_upgrade.cgi");
print &ui_table_start($text{'apt_header'}, undef, 2);
print &ui_table_row($text{'apt_update'},
&ui_yesno_radio("update", 1));
print &ui_table_row($text{'apt_mode'},
&ui_radio("mode", 0, [ [ 2, $text{'apt_mode2'} ],
[ 1, $text{'apt_mode1'} ],
[ 0, $text{'apt_mode0'} ] ]));
print &ui_table_row($text{'apt_sim'},
&ui_yesno_radio("sim", 0));
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'apt_apply'} ] ]);
}
# update_system_resolve(name)
# Converts a standard package name like apache, sendmail or squid into
# the name used by APT.
sub update_system_resolve
{
local ($name) = @_;
return $name eq "dhcpd" && $gconfig{'os_version'} >= 7 ?
"isc-dhcp-server" :
$name eq "dhcpd" && $gconfig{'os_version'} < 7 ?
"dhcp3-server" :
$name eq "bind" ? "bind9" :
$name eq "mysql" && $gconfig{'os_version'} >= 10 ?
"mariadb-client mariadb-server" :
$name eq "mysql" && $gconfig{'os_version'} >= 7 ?
"mysql-client mysql-server" :
$name eq "mysql" && $gconfig{'os_version'} < 7 ?
"mysql-client mysql-server mysql-admin" :
$name eq "apache" ? "apache2" :
$name eq "squid" && $gconfig{'os_version'} <= 9 ?
"squid3" :
$name eq "postgresql" ? "postgresql postgresql-client" :
$name eq "openssh" ? "ssh" :
$name eq "openldap" ? "slapd" :
$name eq "ldap" ? "libnss-ldap libpam-ldap" :
$name eq "dovecot" ? "dovecot-common dovecot-imapd dovecot-pop3d" :
$name eq "virtualmin-modules" ? "webmin-.*" :
$name;
}
# update_system_available()
# Returns a list of package names and versions that are available from APT
sub update_system_available
{
local (@rv, $pkg, %done);
# Use dump to get versions
&execute_command("$apt_get_command update");
&clean_language();
&open_execute_command(DUMP, "apt-cache dumpavail 2>/dev/null", 1, 1);
while(<DUMP>) {
if (/^\s*Package:\s*(\S+)/) {
$pkg = { 'name' => $1 };
push(@rv, $pkg);
$done{$1} = $pkg;
}
elsif (/^\s*Version:\s*(\S+)/ && $pkg && !$pkg->{'version'}) {
$pkg->{'version'} = $1;
if ($pkg->{'version'} =~ /^(\d+):(.*)$/) {
$pkg->{'epoch'} = $1;
$pkg->{'version'} = $2;
}
}
elsif (/^\s*File:\s*(\S+)/ && $pkg) {
$pkg->{'file'} ||= $1;
}
}
close(DUMP);
&reset_environment();
# Use search to get descriptions
foreach my $s (&update_system_search('.*')) {
my $pkg = $done{$s->{'name'}};
if ($pkg) {
$pkg->{'desc'} = $s->{'desc'};
}
}
&set_pinned_versions(\@rv);
return @rv;
}
# update_system_search(text)
# Returns a list of packages matching some search
sub update_system_search
{
local (@rv, $pkg);
&clean_language();
&open_execute_command(DUMP, "$apt_search_command search ".
quotemeta($_[0])." 2>/dev/null", 1, 1);
while(<DUMP>) {
if (/^(\S+)\s*-\s*(.*)/) {
push(@rv, { 'name' => $1, 'desc' => $2 });
}
elsif (/^(\S)\s+(\S+)\s+-\s*(.*)/) {
push(@rv, { 'name' => $2, 'desc' => $3 });
}
}
close(DUMP);
&reset_environment();
return @rv;
}
# update_system_updates()
# Returns a list of available package updates
sub update_system_updates
{
&execute_command("$apt_get_command update");
# Find held packages by dpkg
local %holds;
if ($config{'package_system'} eq 'debian') {
&clean_language();
&open_execute_command(HOLDS, "dpkg --get-selections", 1, 1);
while(<HOLDS>) {
if (/^(\S+)\s+hold/) {
$holds{$1}++;
}
}
close(HOLDS);
&reset_environment();
}
if (&has_command("apt-show-versions")) {
# This awesome command can give us all updates in one hit, and takes
# pinned versions and backports into account
local @rv;
&clean_language();
&execute_command("apt-show-versions -i");
&open_execute_command(PKGS, "apt-show-versions 2>/dev/null", 1, 1);
while(<PKGS>) {
if (/^(\S+)\/(\S+)\s+upgradeable\s+from\s+(\S+)\s+to\s+(\S+)/ &&
!$holds{$1}) {
# Old format
local $pkg = { 'name' => $1,
'source' => $2,
'version' => $4 };
if ($pkg->{'version'} =~ s/^(\S+)://) {
$pkg->{'epoch'} = $1;
}
push(@rv, $pkg);
}
elsif (/^(\S+):(\S+)\/(\S+)\s+(\S+)\s+upgradeable\s+to\s+(\S+)/ && !$holds{$1}) {
# New format, like
# libgomp1:i386/unstable 4.8.2-2 upgradeable to 4.8.2-4
local $pkg = { 'name' => $1,
'arch' => $2,
'source' => $3,
'version' => $5 };
if ($pkg->{'version'} =~ s/^(\S+)://) {
$pkg->{'epoch'} = $1;
}
push(@rv, $pkg);
}
}
close(PKGS);
&reset_environment();
@rv = &filter_held_packages(@rv);
foreach my $pkg (@rv) {
$pkg->{'security'} = 1 if ($pkg->{'source'} =~ /security/i);
}
return @rv;
}
elsif (&has_command("apt")) {
# Use the apt list command
local @rv;
&clean_language();
&open_execute_command(PKGS, "apt list --upgradable 2>/dev/null", 1, 1);
while(<PKGS>) {
if (/^(\S+)\/(\S+)\s+(\S+)\s+(\S+)\s+\[upgradable\s+from:\s+(\S+)\]/ && !$holds{$1}) {
local $pkg = { 'name' => $1,
'source' => $2,
'version' => $3,
'arch' => $4 };
if ($pkg->{'version'} =~ s/^(\S+)://) {
$pkg->{'epoch'} = $1;
}
$pkg->{'source'} =~ s/,.*$//;
push(@rv, $pkg);
}
}
close(PKGS);
&reset_environment();
@rv = &filter_held_packages(@rv);
foreach my $pkg (@rv) {
$pkg->{'security'} = 1 if ($pkg->{'source'} =~ /security/i);
}
return @rv;
}
else {
# Need to manually compose by calling dpkg and apt-cache showpkg
local %packages;
local $n = &list_packages();
local %currentmap;
for(my $i=0; $i<$n; $i++) {
local $pkg = { 'name' => $packages{$i,'name'},
'oldversion' => $packages{$i,'version'},
'desc' => $packages{$i,'desc'},
'oldepoch' => $packages{$i,'epoch'} };
$currentmap{$pkg->{'name'}} ||= $pkg;
}
local @rv;
local @names = grep { !$holds{$_} } keys %currentmap;
while(scalar(@names)) {
local @somenames;
if (scalar(@names) > 100) {
# Do 100 at a time
@somenames = @names[0..99];
@names = @names[100..$#names];
}
else {
# Do the rest
@somenames = @names;
@names = ( );
}
&clean_language();
&open_execute_command(PKGS, "apt-cache showpkg ".
join(" ", @somenames)." 2>/dev/null", 1, 1);
local $pkg = undef;
while(<PKGS>) {
s/\r|\n//g;
if (/^\s*Package:\s*(\S+)/) {
$pkg = $currentmap{$1};
}
elsif (/^Versions:\s*$/ && $pkg && !$pkg->{'version'}) {
# Newest version is on next line
local $ver = <PKGS>;
$ver =~ s/\s.*\r?\n//;
local $epoch;
if ($ver =~ s/^(\d+)://) {
$epoch = $1;
}
$pkg->{'version'} = $ver;
$pkg->{'epoch'} = $epoch;
local $newer =
$pkg->{'epoch'} <=> $pkg->{'oldepoch'} ||
&compare_versions($pkg->{'version'},
$pkg->{'oldversion'});
if ($newer > 0) {
push(@rv, $pkg);
}
}
}
close(PKGS);
&reset_environment();
}
@rv = &filter_held_packages(@rv);
&set_pinned_versions(\@rv);
return @rv;
}
}
# set_pinned_versions(&package-list)
# Updates the version and epoch fields in a list of available packages based
# on pinning.
sub set_pinned_versions
{
local ($pkgs) = @_;
local %pkgmap = map { $_->{'name'}, $_ } @$pkgs;
&clean_language();
&open_execute_command(PKGS, "apt-cache policy 2>/dev/null", 1, 1);
while(<PKGS>) {
s/\r|\n//g;
if (/\s+(\S+)\s+\-\>\s+(\S+)/) {
my ($name, $pin) = ($1, $2);
my $pkg = $pkgmap{$name};
if ($pkg) {
$pkg->{'version'} = $pin;
$pkg->{'epoch'} = undef;
if ($pkg->{'version'} =~ s/^(\S+)://) {
$pkg->{'epoch'} = $1;
}
}
}
}
close(PKGS);
&reset_environment();
}
# filter_held_packages(package, ...)
# Returns a list of package updates, minus those that are held
sub filter_held_packages
{
my @pkgs = @_;
my %hold;
# Get holds from dpkg
&clean_language();
&open_execute_command(PKGS, "dpkg --get-selections 2>/dev/null", 1, 1);
while(<PKGS>) {
if (/^(\S+)\s+hold/) {
$hold{$1} = 1;
}
}
close(PKGS);
&reset_environment();
# Get holds from aptitude
if (&has_command("aptitude")) {
&clean_language();
&open_execute_command(PKGS, "aptitude search '~ahold' 2>/dev/null", 1, 1);
while(<PKGS>) {
if (/^\.h\s+(\S+)/) {
$hold{$1} = 1;
}
}
close(PKGS);
&reset_environment();
}
# Get holds from apt-mark
if (&has_command("apt-mark")) {
&clean_language();
&open_execute_command(PKGS, "apt-mark showhold 2>/dev/null", 1, 1);
while(<PKGS>) {
if (/^([^:\s]+)/) {
$hold{$1} = 1;
}
}
close(PKGS);
&reset_environment();
}
return grep { !$hold{$_->{'name'}} } @pkgs;
}
# list_package_repos()
# Returns a list of configured repositories
sub list_package_repos
{
my @rv;
# Read all repos files
foreach my $f ($sources_list_file, glob("$sources_list_dir/*")) {
my $lref = &read_file_lines($f, 1);
my $lnum = 0;
my (%repo, @types);
my $repo_proc = sub {
foreach my $type (@types) {
my @suites = @{$repo{'suites'}};
foreach my $suite (@suites) {
my @comps = @{$repo{'comps'}};
foreach my $comp (@comps) {
my $repo =
{
'cannot' => 1,
'file' => $f,
'url' => $repo{'url'},
'enabled' => !$repo{'disabled'},
'words' => [$comp, $suite],
'name' => join("/", $comp, $suite).
($type =~ /src/ ? " ($type)" : ""),
'signed_by' => $repo{'signed_by'},
};
$repo->{'id'} =
$repo->{'url'}.$repo->{'name'};
push(@rv, $repo);
}
}
}
};
foreach my $l (@$lref) {
# Debian classic format (using .list files)
if ($l =~ /^(#*)\s*deb.*?((http|https)\S+)\s+(\S.*)/) {
my $repo = { 'file' => $f,
'line' => $lnum,
'words' => \@w,
'url' => $2,
'enabled' => !$1 };
my @w = split(/\s+/, $4);
my $type =
($l =~ /^(#*)\s*(deb-src)/) ? " ($2)" : "";
$repo->{'name'} = join("/", @w).$type;
$repo->{'id'} = $repo->{'url'}.$repo->{'name'};
push(@rv, $repo);
}
# New Ubuntu-style repos (using .sources files)
elsif ($f =~ /\.sources$/) {
if ($l =~ /^([\w\-]+):\s*(.+)$/) {
my ($key, $value) = ($1, $2);
if ($key eq 'Types') {
@types = split(/\s+/, $value);
}
elsif ($key eq 'URIs') {
$repo{'url'} = $value;
}
elsif ($key eq 'Suites') {
$repo{'suites'} = [split(/\s+/, $value)];
}
elsif ($key eq 'Components') {
$repo{'comps'} = [split(/\s+/, $value)];
}
elsif ($key eq 'Signed-By') {
$repo{'signed_by'} = $value;
}
elsif ($key eq 'Enabled') {
$repo{'disabled'} =
(lc($value) eq 'no') ? 1 : 0;
}
}
if (($l =~ /^\s*$/ || $lnum == $#{$lref}) && %repo) {
# Process and push the current repo if we
# got an empty line or it's the last line
$repo_proc->();
%repo = ();
@types = ();
}
}
$lnum++;
}
}
return @rv;
}
# create_repo_form()
# Returns HTML for a package repository creation form
sub create_repo_form
{
my $rv;
$rv .= &ui_table_row($text{'apt_repo_url'},
&ui_textbox("url", undef, 40));
$rv .= &ui_table_row($text{'apt_repo_path'},
&ui_textbox("path", undef, 40));
return $rv;
}
# create_repo_parse(&in)
# Parses input from create_repo_form, and returns either a new repo object or
# an error string
sub create_repo_parse
{
my ($in) = @_;
my $repo = { 'enabled' => 1 };
# Parse base URL
$in->{'url'} =~ /^(http|https|ftp|file):\S+$/ ||
return $text{'apt_repo_eurl'};
$repo->{'url'} = $in->{'url'};
# Parse distro components
my @w = split(/\s+|\//, $in->{'path'});
@w || $text{'apt_repo_epath'};
$repo->{'name'} = join("/", @w);
$repo->{'id'} = $repo->{'url'}.$repo->{'name'};
return $repo;
}
# create_package_repo(&repo)
# Creates a new repository from the given hash (returned by create_repo_parse)
sub create_package_repo
{
my ($repo) = @_;
&lock_file($sources_list_file);
my $lref = &read_file_lines($sources_list_file);
push(@$lref, ($repo->{'enabled'} ? "" : "# ").
"deb ".
$repo->{'url'}." ".
join(" ", split(/\//, $repo->{'name'})));
&flush_file_lines($sources_list_file);
&unlock_file($sources_list_file);
return undef;
}
# delete_package_repo(&repo)
# Delete a repo from the sources.list file
sub delete_package_repo
{
my ($repo) = @_;
&lock_file($repo->{'file'});
my $lref = &read_file_lines($repo->{'file'});
splice(@$lref, $repo->{'line'}, 1);
&flush_file_lines($repo->{'file'});
&unlock_file($repo->{'file'});
}
# enable_package_repo(&repo, enable?)
# Enable or disable a repository
sub enable_package_repo
{
my ($repo, $enable) = @_;
&lock_file($repo->{'file'});
my $lref = &read_file_lines($repo->{'file'});
$lref->[$repo->{'line'}] =~ s/^#+\s*//;
if (!$enable) {
$lref->[$repo->{'line'}] = "# ".$lref->[$repo->{'line'}];
}
&flush_file_lines($repo->{'file'});
&unlock_file($repo->{'file'});
}
1;
+71
View File
@@ -0,0 +1,71 @@
#!/usr/local/bin/perl
# apt_upgrade.cgi
# Upgrade a debian system
require './software-lib.pl';
&ReadParse();
&ui_print_unbuffered_header(undef, $text{'apt_upgrade'}, "");
if ($in{'update'}) {
print "<b>",&text('apt_updatedesc',
"<tt>$apt_get_command update</tt>"),"</b><p>\n";
print "<pre>";
&additional_log("exec", undef, "$apt_get_command update");
&clean_environment();
open(CMD, "$apt_get_command update 2>&1 </dev/null |");
while(<CMD>) {
print &html_escape($_);
}
close(CMD);
&reset_environment();
print "</pre>\n";
if ($?) {
print "<b>$text{'apt_updatefailed'}</b><p>\n";
&ui_print_footer("?tab=update", $text{'index_return'});
exit;
}
else { print "<b>$text{'apt_updateok'}</b><p>\n"; }
}
if ($in{'mode'}) {
$opts = $in{'sim'} ? "-s -y -f" : "-y -f";
$cmd = $in{'mode'} == 2 ? "dist-upgrade" :
$apt_get_command =~ /aptitude/ ? "safe-upgrade" : "upgrade";
print "<b>",&text($in{'sim'} ? 'apt_upgradedescsim' : 'apt_upgradedesc', "<tt>$apt_get_command $opts $cmd</tt>"),"</b><p>\n";
print "<pre>";
&additional_log("exec", undef, "$apt_get_command $opts $cmd");
&clean_environment();
open(CMD, "$apt_get_command $opts $cmd 2>&1 </dev/null |");
while(<CMD>) {
if (/setting\s+up\s+(\S+)/i) {
push(@packs, $1);
}
elsif (/packages\s+will\s+be\s+upgraded/i ||
/new\s+packages\s+will\s+be\s+installed/i) {
print &html_escape($_);
$line = $_ = <CMD>;
$line =~ s/^\s+//; $line =~ s/\s+$//;
push(@newpacks, split(/\s+/, $line));
}
print;
}
close(CMD);
&reset_environment();
if (!@rv && $config{'package_system'} ne 'debian' && !$?) {
# Other systems don't list the packages installed!
@packs = @newpacks;
}
print "</pre>\n";
if ($?) { print "<b>$text{'apt_upgradefailed'}</b><p>\n"; }
else { print "<b>$text{'apt_upgradeok'}</b><p>\n"; }
foreach $p (@packs) {
local @pinfo = &show_package_info($p);
}
&webmin_log("apt", "check", undef, { 'packages' => \@packs })
if (@packs);
}
&ui_print_footer("?tab=update", $text{'index_return'});
+25
View File
@@ -0,0 +1,25 @@
do 'software-lib.pl';
sub cgi_args
{
my ($cgi) = @_;
if ($cgi eq 'search.cgi') {
# Example search
return 'search=ssh';
}
elsif ($cgi eq 'edit_pack.cgi' || $cgi eq 'list_pack.cgi') {
# Package for /bin/ls
local %file;
&installed_file('/bin/ls');
my @pkgs = split(/\s+/, $file{'packages'});
my @vers = split(/\s+/, $file{'versions'});
return 'package='.&urlize($pkgs[0]).
'&version='.&urlize($vers[0]);
}
elsif ($cgi eq 'file_info.cgi') {
# Info on file /bin/ls
return 'file=/bin/ls';
}
return undef;
}
+10
View File
@@ -0,0 +1,10 @@
#!/usr/local/bin/perl
# close.cgi
# Remove some class from the open list
require './software-lib.pl';
&ReadParse();
@heiropen = &get_heiropen();
@heiropen = grep { $_ ne $in{'what'} } @heiropen;
&save_heiropen(\@heiropen);
&redirect("tree.cgi#".&urlize($in{'what'}));
+2
View File
@@ -0,0 +1,2 @@
package_system=aix
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=apk
update_system=apk
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=debian
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=cygwin
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
package_system=debian
update_system=apt
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
package_system=freebsd
update_system=ports
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
package_system=freebsd
update_system=pkg
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=emerge
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=hpux
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=freebsd
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=openbsd
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
package_system=rpm
update_system=apt
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=pkgadd
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
package_system=rpm
update_system=yum
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=slackware
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=pkgadd
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
apt_mode=0
package_system=ipkg
update_system=ipkg
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=rpm
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=pkgadd
apt_mode=0
+2
View File
@@ -0,0 +1,2 @@
package_system=msi
apt_mode=0
+3
View File
@@ -0,0 +1,3 @@
package_system=Package management system,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,apk-Alpine APK,cygwin-Cygwin,msi-Microsoft Installer,pkgsrc-PKGsrc,ipkg-Synology IPKG
update_system=Package update system,1,-Detect automatically,apt-APT,yum-YUM,rhn-Redhat Network,csw-Blastwave CSW,urpmi-URPMI,emerge-Emerge,apk-Alpine APK,ports-FreeBSD Ports,pkg-FreeBSD pkgng,pkgsrc-PKGsrc,ipkg-Synology IPKG update,*-None
apt_mode=Command to use for APT installs,1,0-apt&#45;get,1-aptitude
+3
View File
@@ -0,0 +1,3 @@
package_system=Sistema de gestió de paquets,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin,msi-Instal·lador Microsoft,pkgsrc-PKGsrc,ipkg-Synology IPKG
update_system=Sistema d'actualització de paquets,1,-Detecta'l automàticament,apt-APT,yum-YUM,rhn-Xarxa de Redhat,csw-CSW Blastwave,urpmi-URPMI,emerge-Emerge,ports-FreeBSD Ports,pkg-FreeBSD pkgng,pkgsrc-PKGsrc,ipkg-Synology IPKG update,*-Cap
apt_mode=Ordre a utilitzar per a les instal·lacions APT,1,0-apt&#45;get,1-aptitude
+3
View File
@@ -0,0 +1,3 @@
package_system=Balíčky systémové správy,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo
update_system=Systém pro aktualizaci balíčků,1,-Detekovat automaticky,apt-APT,yum-YUM,rhn-Redhat Network,csw-Blastwave,urpmi-URPMI,emerge-Emerge
apt_mode=Příkaz pro užití APT instalace,1,0-apt&#45;get,1-aptitute
+3
View File
@@ -0,0 +1,3 @@
package_system=System Paket&#45;Management,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin,msi-Microsoft Installer,pkgsrc-PKGsrc,ipkg-Synology IOKG
update_system=Paket&#45;Update&#45;System,1,-Automatisch erkennen,apt-APT,yum-YUM,rhn-Redhat Network,csw-Blastwave CSW,urpmi-URPMI,emerge-Emerge,ports-FreeBSD Ports,pkg-FreeBSD pkgng,pkgsrc-PKGsrc,ipkg-Synology IPKG Update,*-Kein
apt_mode=Befehl&#44; um APTs zu installieren,1,0-apt&#45;get,1-aptitude
+2
View File
@@ -0,0 +1,2 @@
package_system=Sistema de gestión de Paquetes,4,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin
update_system=Sistema de actualización de Paquetes,1,-Detectar automáticamente,apt-APT,yum-YUM,rhm-Red Redhat,csw-Blastwave,urpmi-URPMI,emerge-Emerge
+1
View File
@@ -0,0 +1 @@
package_system=Système de gestion des composants,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian
+3
View File
@@ -0,0 +1,3 @@
package_system=パッケージ管理システム,4,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin,msi-Microsoft Installer
update_system=パッケージアップデートシステム,1,-自動判別,apt-APT,yum-YUM,rhn-Redhat Network,csw-Blastwave,urpmi-URPMI,emerge-Emerge
apt_mode=APT のインストールに使うコマンド,1,0-apt&#45;get,1-aptitute
+3
View File
@@ -0,0 +1,3 @@
package_system=패키지 관리 시스템,4,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin,msi-Microsoft Installer
update_system=패키지 업데이트 시스템,1,-자동 감지,apt-APT,yum-YUM,rhn-Redhat 네트워크,csw-Blastwave,urpmi-URPMI,emerge-Emerge
apt_mode=APT 설치를 위해 사용할 명령,1,0-apt&#45;get,1-aptitute
+3
View File
@@ -0,0 +1,3 @@
package_system=Sistem pengurusan pakej,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin
update_system=Pakej kemaskini sistem,1,-Kesan secara automatik,apt-APT,yum-YUM,rhn-Rangkaian Redhat,csw-Blastwave CSW,urpmi-URPMI,emerge-Emerge,ports-Ports,*-Tiada
apt_mode=Arahan yang digunakan ketika proses pemasangan APT,1,0-apt&#45;get,1-aptitude
+3
View File
@@ -0,0 +1,3 @@
package_system=Pakket management systeem,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin,msi-Microsoft Installer
update_system=Pakket update syteem,1,-Detecteer automatisch,apt-APT,yum-YUM,rhn-Redhat Netwerk,cws-Blastwave CSW,urpmi-URPMI,emerge-Emerge,*-Geen
apt_mode=Opdracht om te gebruiken voor APT installaties,1,0-apt&#45;get,1-aptitude
+3
View File
@@ -0,0 +1,3 @@
package_system=Vedlikeholdssystem for pakker,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo,cygwin-Cygwin,msi-Microsoft Installer
update_system=Oppdateringssystem for pakker,1,-Oppdag automatisk,apt-APT,yum-YUM,rhn-Redhat Network,csw-Blastwave CSW,urpmi-URPMI,emerge-Emerge,*-Ingen
apt_mode=Kommando som skal brukes i APT installeringer,1,0-apt&#45;get,1-aptitude
+3
View File
@@ -0,0 +1,3 @@
package_system=System zarządzania pakietami,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian
update_system=System aktualizacji pakietu,1,-Automatycznie,apt-APT,yum-YUM,rhn-Redhat Network,csw-Blastwave CSW,urpmi-URPMI,emerge-Emerge,ports-FreeBSD Ports,pkg-FreeBSD pkgng,pkgsrc-PKGsrc,*-Brak
apt_mode=Polecenie instalacji dla APT,1,0-apt&#45;get,1-aptitude
+1
View File
@@ -0,0 +1 @@
package_system=Система управления пакетами,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo
+2
View File
@@ -0,0 +1,2 @@
package_system=Pakethanteringssystem,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian
update_system=Automatiskt installationssystem,1,apt-Debian APT,rhn-Redhat Network,cup-Caldera CUPDATE
+1
View File
@@ -0,0 +1 @@
package_system=Paket yönetim sistemi,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian
+1
View File
@@ -0,0 +1 @@
package_system=Система керування пакетами,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian,aix-AIX,emerge-Gentoo
+1
View File
@@ -0,0 +1 @@
package_system=软件包管理系统,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian
+1
View File
@@ -0,0 +1 @@
package_system=套件管理系統類別,1,rpm-RPM,pkgadd-Solaris,hpux-HPUX,freebsd-FreeBSD,slackware-Slackware,debian-Debian
+118
View File
@@ -0,0 +1,118 @@
# csw-lib.pl
# Functions for installing packages from Blastwave
$pkg_get = -x "/opt/csw/bin/pkgutil" ? "/opt/csw/bin/pkgutil" :
-x "/opt/csw/bin/pkg-get" ? "/opt/csw/bin/pkg-get" :
&has_command("pkgutil") ? &has_command("pkgutil") :
&has_command("pkg-get");
sub list_update_system_commands
{
return ($pkg_get);
}
# update_system_install([file])
# Install some package with pkg-get
sub update_system_install
{
local $update = $_[0] || $in{'update'};
local (@rv, @newpacks, %seen, $failed);
# Setup for non-interactive mode
&copy_source_dest("/var/pkg-get/admin", "/var/pkg-get/admin-old");
&copy_source_dest("/var/pkg-get/admin-fullauto", "/var/pkg-get/admin");
# Run pkg-get
$| = 1;
local ($failed, $retry, %already);
do {
if ($already{$update}++) {
# Don't try the same update twice
last;
}
local $flag = $pkg_get =~ /pkgutil$/ ? "-y" : "-f";
print &text('csw_install',
"<tt>$pkg_get -i $flag $update</tt>"),"\n";
$failed = 0;
$retry = 0;
print "<pre data-installer>";
&open_execute_command(PKGGET,
"$pkg_get -i $flag ".quotemeta($update), 2);
while(<PKGGET>) {
if (!/\s*\d+\%\s+\[/) {
# Output everything except download lines
print &html_escape($_);
}
if (/Installation of <(.*)> was successful/i) {
push(@rv, $1);
}
elsif (/Installation of <(.*)> failed/i) {
$failed = 1;
}
elsif (/dependency\s+(\S+)\s+.*not up to date/i) {
# Needs a dependency .. so we will need to re-run!
local $dep = $1;
$update = join(" ", &unique(
$dep, split(/\s+/, $update)));
$retry = 1;
}
elsif (/you already have version/i) {
$failed = 2;
}
}
close(PKGGET);
print "</pre>";
if ($retry) {
print "$text{'csw_retry'}<p>\n";
}
} while ($retry);
# Cleanup fullout file
&copy_source_dest("/var/pkg-get/admin-old", "/var/pkg-get/admin");
if ($failed == 1) {
print "$text{'csw_failed'}<p>\n";
return ( );
}
elsif ($failed == 2) {
print "$text{'csw_already'}<p>\n";
return ( );
}
else {
print "$text{'csw_ok'}<p>\n";
if (!@rv) {
# If nothing failed, assume that everything worked
@rv = split(/\s+/, $update);
}
return @rv;
}
}
# update_system_available()
# Returns a list of all available CSW packages
sub update_system_available
{
local @rv;
open(PKG, "$pkg_get -a |");
while(<PKG>) {
s/\r|\n//g;
s/#.*$//;
next if (/^\s*WARNING:/);
if (/^\s*(\S+)\s+(\S+)\s+(\d\S+)\s+([0-9\.]+)\s+(KB|MB|GB|B)/i) {
# New pkgutil format
push(@rv, { 'name' => $1, 'version' => $3,
'select' => "$1-$3" });
}
elsif (/^\s*(\S+)\s+(\S+)/) {
# Old pkg-get format
push(@rv, { 'name' => $1, 'version' => $2,
'select' => "$1-$2" });
}
}
close(PKG);
return sort { lc($a->{'name'}) cmp lc($b->{'name'}) } @rv;
}
1;
+807
View File
@@ -0,0 +1,807 @@
# cygwin-lib.pl
# Functions for cygwin + redhat package management
use vars '$hasrpm'; $hasrpm = (-f "/usr/bin/rpm.exe");
use vars '$db'; $db = "/etc/setup/installed.db";
sub validate_package_system
{
return -r $db ? undef : &text('cygwin_edb', "<tt>$db</tt>");
}
# list_packages([package]*)
# Fills the array %packages with all or listed packages
sub list_packages
{
my (@pkgs) = @_;
my $allpkgs = (@_ == 0);
local($i, $list); $i = 0;
%packages = ( );
if (&open_tempfile(DB, $db)) {
while (<DB>) {
#suppress packages that begin with an underscore
if (/^([^_][^\s]*)\s+([^\s]+)\s+(\d+)/) {
#TODO: classes, descriptions
my ($name, $ver, $class, $desc) = ($1, $2, "cygwin", "");
my $qmname = quotemeta($name);
next if ! $allpkgs && ! grep(/^$qmname$/, @pkgs);
$ver =~ s/.*?[_\-](\d.*)\.tar\..*/$1/;
$packages{$i, 'name'} = $name;
$packages{$i, 'class'} = $class;
$packages{$i, 'version'} = $ver;
$packages{$i, 'desc'} = $desc;
$i++;
@pkgs = grep { $_ ne $name } @pkgs if ! $allpkgs;
}
last if (! $allpkgs && @pkgs == 0);
}
close(DB);
@_ = @pkgs;
}
return $i if ! $hasrpm || (! $allpkgs && @pkgs == 0);
$list = @_ ? join(' ', map { quotemeta($_) } @_) : "-a";
&open_execute_command(RPM, "rpm -q $list --queryformat \"%{NAME}\\n%{VERSION}-%{RELEASE}\\n%{GROUP}\\n%{SUMMARY}\\n\\n\"", 1, 1);
while($packages{$i,'name'} = <RPM>) {
chop($packages{$i,'name'});
chop($packages{$i,'version'} = <RPM>);
chop($packages{$i,'class'} = <RPM>);
while(<RPM>) {
s/\r|\n/ /g;
last if (!/\S/);
$packages{$i,'desc'} .= $_;
}
$i++;
}
close(RPM);
return $i;
}
# package_info(package, version)
# Returns an array of package information in the order
# name, class, description, arch, version, vendor, installtime
sub package_info
{
my @cygdata = cygwin_pkg_info(@_);
return @cygdata if @cygdata > 0;
return undef if ! $hasrpm;
local(@rv, @tmp, $d);
local $n = $_[1] ? "$_[0]-$_[1]" : $_[0];
local $qm = quotemeta($n);
&open_execute_command(RPM, "rpm -q $qm --queryformat \"%{NAME}\\n%{GROUP}\\n%{ARCH}\\n%{VERSION}-%{RELEASE}\\n%{VENDOR}\\n%{INSTALLTIME}\\n\" 2>/dev/null", 1, 1);
@tmp = <RPM>;
chop(@tmp);
if (!@tmp) { return (); }
close(RPM);
&open_execute_command(RPM, "rpm -q $qm --queryformat \"%{DESCRIPTION}\"", 1, 1);
while(<RPM>) { $d .= $_; }
close(RPM);
return ($tmp[0], $tmp[1], $d, $tmp[2], $tmp[3], $tmp[4], &make_date($tmp[5]));
}
# virtual_package_info(package)
# Returns an array of package information for a virtual package, usually called
# if "package_info" returns nothing.
sub virtual_package_info
{
return ( );
}
# is_package(file)
# Check if some file is a package file
sub is_package
{
local($out);
local $real = &translate_filename($_[0]);
if (-d $_[0]) {
# a directory .. see if it contains any .rpm or .tar.bz2 files
opendir(DIR, $real);
local @list = grep { /([^\s]+[_\-](\d[^\s]*|src)-\d[^\s]*\.tar\.bz2|\.rpm)$/} readdir(DIR);
closedir(DIR);
return @list ? 1 : 0;
}
elsif ($_[0] =~ /\*|\?/) {
# a wildcard .. see what it matches
local @list = glob($real);
return @list ? 1 : 0;
}
else {
# just a normal file ..check if it is an RPM and not an SRPM or tar.bz2
return 1 if $_[0] =~ /[^\s]+[_\-](\d[^\s]*|src)-\d[^\s]*\.tar\.bz2$/;
local $qm = quotemeta($_[0]);
$out = &backquote_command("rpm -q -p $qm 2>&1", 1);
if ($out =~ /does not appear|No such file|with major numbers/i) {
return 0;
}
&open_execute_command(OUT, "rpm -q -p -l $qm 2>&1", 1, 1);
while(<OUT>) {
return 0 if (/^([^\/\s]+)\.spec$/);
}
close(OUT);
return 1;
}
}
# file_packages(file)
# Returns a list of all packages in the given file, in the form
# package-version description
sub file_packages
{
local $real = &translate_filename($_[0]);
local $qm = quotemeta($_[0]);
if (-d $real) {
local @rv;
opendir(DIR, $real);
@rv = grep { s/.*\/([^\s]+)[_\-]((\d[^\s]*|src)-\d[^\s]*)\.tar\.bz2$/$1/ } readdir(DIR);
closedir(DIR);
&open_execute_command(RPM, "cd $qm && rpm -q -p *.rpm --queryformat \"%{NAME} %{SUMMARY}\\n\" 2>&1", 1, 1);
while(<RPM>) {
chop;
push(@rv, $_) if (!/does not appear|query of.*failed|warning:/);
}
close(RPM);
return @rv;
}
elsif ($_[0] =~ /\*|\?/) {
local @rv;
my $qm = quotemeta($_[0]);
$qm =~ s/\\([*?])/$1/g;
my @p = &backquote_command("ls $qm");
@rv = grep { s/.*\/([^\s]+)[_\-]((\d[^\s]*|src)-\d[^\s]*)\.tar\.bz2$/$1/ } @p;
&open_execute_command(RPM, "rpm -q -p $qm --queryformat \"%{NAME} %{SUMMARY}\\n\" 2>&1", 1);
while(<RPM>) {
chop;
push(@rv, $_) if (!/does not appear|query of.*failed|warning:/);
}
close(RPM);
return @rv;
}
else {
local($out);
$out = $_[0];
return $out
if $out =~ s/.*\/([^\s]+)[_\-]((\d[^\s]*|src)-\d[^\s]*)\.tar\.bz2$/$1/;
$out = &backquote_command("rpm -q -p $qm --queryformat \"%{NAME} %{SUMMARY}\\n\" 2>&1", 1);
$out =~ s/warning:.*\n//;
$out =~ s/\n//g;
return ($out);
}
}
# install_options(file, package)
# Outputs HTML for choosing install options for some package
sub install_options
{
my ($file, $pkg) = @_;
if ($file =~ /\/[^\s]+[_\-]src[_\-]\d[^\s]*\.tar\.bz2$/) {
# No options
} elsif ($file =~ /\/[^\s]+[_\-]\d[^\s]*-\d[^\s]*\.tar\.bz2$/) {
print &ui_table_row(undef, "<b>$text{'cygwin_warnuse'}</b>", 4);
print &yesno_input($text{'rpm_upgrade'}, "upgrade", 1, 0, 1);
print &yesno_input($text{'rpm_replacepkgs'}, "replacepkgs", 1, 0);
print &yesno_input($text{'rpm_noscripts'}, "noscripts", 0, 1);
} else {
print &yesno_input($text{'rpm_upgrade'}, "upgrade", 1, 0, 1);
print &yesno_input($text{'rpm_replacepkgs'}, "replacepkgs", 1, 0);
print &yesno_input($text{'rpm_nodeps'}, "nodeps", 1, 0);
print &yesno_input($text{'rpm_oldpackage'}, "oldpackage", 1, 0);
print &yesno_input($text{'rpm_noscripts'}, "noscripts", 0, 1);
print &yesno_input($text{'rpm_excludedocs'}, "excludedocs", 0, 1);
print &yesno_input($text{'rpm_notriggers'}, "notriggers", 0, 1);
print &yesno_input($text{'rpm_ignoresize'}, "ignoresize", 0, 1);
print &yesno_input($text{'rpm_replacefiles'}, "replacefiles", 1, 0);
}
print &ui_table_row(&hlink($text{'rpm_root'}, "root"),
&ui_textbox("root", "/", 50)." ".
&file_chooser_button("root", 1), 3);
}
sub yesno_input
{
return &ui_table_row(&hlink($_[0], $_[1]),
&ui_radio($_[1], int($_[4]),
[ [ $_[2], $text{'yes'} ],
[ $_[3], $text{'no'} ] ]));
}
# install_package(file, package, [&inputs])
# Install the given package from the given file, using options from %in
sub install_package
{
local $file = $_[0];
local $real = &translate_filename($file);
local $in = $_[2] ? $_[2] : \%in;
local $opts;
foreach $o ('oldpackage', 'replacefiles', 'replacepkgs', 'noscripts',
'excludedocs', 'nodeps', 'upgrade', 'notriggers', 'ignoresize') {
if ($in->{$o}) { $opts .= " --$o"; }
}
if ($in->{'root'} =~ /^\/.+/) {
if (!(-d $in{'root'})) {
return &text('rpm_eroot', $in->{'root'});
}
$opts .= " --root ".quotemeta($in->{'root'});
}
if (-d $real) {
# Find the package in the directory
local ($f, $out);
opendir(DIR, $real);
while($f = readdir(DIR)) {
if ($f =~ /\/([^\s]+[_\-]src[_\-]\d[^\s]*)\.tar\.bz2$/) {
$out = $1;
} elsif ($f =~ /^([^\s]+[_\-]\d[^\s]*-\d[^\s]*)\.tar\.bz2$/) {
$out = $1;
} else {
next if ($f !~ /\.rpm$/);
my $qf = quotemeta("$file/$f");
$out = &backquote_command("rpm -q -p $qf --queryformat \"%{NAME}\\n\" 2>&1");
$out =~ s/warning:.*\n//;
$out =~ s/\n//;
}
if ($out eq $_[1]) {
$file = "$file/$f";
last;
}
}
closedir(DIR);
&error(&text('rpm_erpm', $_[1], $out)) if ($file eq $_[0]);
}
elsif ($file =~ /\*|\?/) {
# Find the package in the glob
# XXX won't work when translation is in effect
local ($f, $out);
foreach $f (glob($real)) {
if ($f =~ /\/([^\s]+[_\-]src[_\-]\d[^\s]*)\.tar\.bz2$/) {
$out = $1;
} elsif ($f =~ /\/([^\s]+[_\-]\d[^\s]*-\d[^\s]*)\.tar\.bz2$/) {
$out = $1;
} else {
my $qf = quotemeta($f);
$out = &backquote_command("rpm -q -p $qf --queryformat \"%{NAME}\\n\" 2>&1", 1);
$out =~ s/warning:.*\n//;
$out =~ s/\n//;
}
if ($out eq $_[1]) {
$file = $f;
last;
}
}
&error(&text('rpm_erpm', $_[1], $out)) if ($file eq $_[0]);
}
local $temp = &transname();
local $rv;
if ($file =~ /\/[^\s]+[_\-]src[_\-]\d[^\s]*\.tar\.bz2$/) {
$rv = install_cygwin_src_pkg($file, $temp, $in->{'root'});
} elsif ($file =~ /\/[^\s]+[_\-]\d[^\s]*-\d[^\s]*\.tar\.bz2$/) {
my $run_scripts = 1;
$run_scripts = 0 if defined($in->{'noscripts'}) && $in->{'noscripts'} == 1;
$rv = install_cygwin_pkg($file, $temp, $in->{'root'}, $run_scripts,
$in->{'replacepkgs'}, $in->{'upgrade'});
} else {
$rv = &system_logged("rpm -i $opts ".quotemeta($file)." >".quotemeta($temp)." 2>&1");
}
local $out = "";
if (! open(FILE, "<$temp")) {
warn "could not open $temp: $!\n";
} else {
$out = join('', <FILE>);
close(FILE);
$out =~ s/warning:.*\n//;
unlink($temp);
}
if ($rv) {
return "<pre>$out</pre>";
}
return undef;
}
#instead of defining install_packages() (which do_install.cgi has a
#couple of design flaws with), make it install them one-by-one.
#<<- no sub install_packages here ->>
# check_files(package, version)
# Fills in the %files array with information about the files belonging
# to some package. Values in %files are path type user group size error
sub check_files
{
local($i, $_, @w, %errs, $epath); $i = 0;
my @cygdata = cygwin_pkg_info(@_);
my $root = "/";
my $origlst = "${root}etc/setup/$cygdata[0].lst.gz";
if (@cygdata && -f $origlst) {
#$name, $class, $desc, $arch, $ver, $vendor, $date
my $lst = uncompress_if_needed($origlst);
if (&open_readfile(FILES, $lst)) {
while (<FILES>) {
chomp($_);
my $f = get_file_info($root . $_);
for (qw(path link type user group size error)) {
$files{$i, $_} = $f->{$_} if defined($f->{$_});
}
$i++;
}
close(FILES);
&unlink_file($lst) if $origlst ne $lst;
}
}
return $i if $i > 0 || ! $hasrpm;
local $n = $_[1] ? "$_[0]-$_[1]" : $_[0];
local $qm = quotemeta($n);
&open_execute_command(RPM, "rpm -V $qm", 1, 1);
while(<RPM>) {
/^(.{8}) (.) (.*)$/;
if ($1 eq "missing ") {
$errs{$3} = $text{'rpm_missing'};
}
else {
$epath = $3;
@w = grep { $_ ne "." } split(//, $1);
$errs{$epath} =
join("\n", map { &text('rpm_checkfail', $etype{$_}) } @w);
}
}
close(RPM);
&open_execute_command(RPM, "rpm -q $qm -l --dump", 1, 1);
while(<RPM>) {
chop;
@w = split(/ /);
$files{$i,'path'} = $w[0];
if ($w[10] ne "X") { $files{$i,'link'} = $w[10]; }
$files{$i,'type'} = $w[10] ne "X" ? 3 :
(-d &translate_filename($w[0])) ? 1 :
$w[7] ? 5 : 0;
$files{$i,'user'} = $w[5];
$files{$i,'group'} = $w[6];
$files{$i,'size'} = $w[1];
$files{$i,'error'} = $w[7] ? "" : $errs{$w[0]};
$i++;
}
close(RPM);
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($pkg, @w, $_, @pkgs, @vers);
undef(%file);
my $root = "/";
my $file = $_[0];
$file =~ s/^$root//;
local $qm = quotemeta($file);
@pkgs = &backquote_command("zgrep -le '^$qm\$' /etc/setup/*.lst.gz 2>&1", 1);
chomp(@pkgs);
if (@pkgs) {
grep(s/.*etc\/setup\/(.+)\.lst\.gz/$1/g, @pkgs);
my $f = get_file_info($root . $file);
$f->{'packages'} = join(' ', @pkgs);
if (&open_readfile(LST, $db)) {
while (<LST>) {
if (/^([^\s]+)\s+[^\s]+[_\-]([\d][^\s]\.tar\.bz2)\s/) {
my ($pkg, $ver) = ($1, $2);
$f->{'versions'} .= "$ver "
if grep(/^$pkg$/, @pkgs);
}
}
close(LST);
}
%file = %$f;
return 1;
} else {
return 0 if ! $hasrpm;
}
local $qm = quotemeta($_[0]);
$pkg = &backquote_command("rpm -q -f $qm --queryformat \"%{NAME}\\n\" 2>&1", 1);
if ($pkg =~ /not owned/ || $?) { return 0; }
@pkgs = split(/\n/, $pkg);
$pkg = &backquote_command("rpm -q -f $qm --queryformat \"%{VERSION}-%{RELEASE}\\n\" 2>&1");
@vers = split(/\n/, $pkg);
&open_execute_command(RPM, "rpm -q $pkgs[0] -l --dump", 1, 1);
while(<RPM>) {
chop;
@w = split(/ /);
if ($w[0] eq $_[0]) {
$file{'packages'} = join(' ', @pkgs);
$file{'versions'} = join(' ', @vers);
$file{'path'} = $w[0];
if ($w[10] ne "X") { $files{$i,'link'} = $w[10]; }
$file{'type'} = $w[10] ne "X" ? 3 :
(-d &translate_filename($w[0])) ? 1 :
$w[7] ? 5 : 0;
$file{'user'} = $w[5];
$file{'group'} = $w[6];
$file{'mode'} = substr($w[4], -4);
$file{'size'} = $w[1];
last;
}
}
close(RPM);
return 1;
}
# delete_options(package)
# Outputs HTML for package uninstall options
sub delete_options
{
my @cygdata = cygwin_pkg_info(@_);
if (@cygdata) {
print "<b>$text{'cygwin_warnuse'}</b><br>\n";
} else {
print "<b>$text{'delete_nodeps'}</b>\n";
print &ui_yesno_radio("nodeps", 0),"<br>\n";
}
print "<b>$text{'delete_noscripts'}</b>\n";
print &ui_yesno_radio("noscripts", 0),"<br>\n";
}
# delete_package(package, [&options], version)
# Attempt to remove some package
sub delete_package
{
local $in = $_[2] ? $_[2] : \%in;
my @cygdata = cygwin_pkg_info($_[0], $_[2]);
if (@cygdata) {
my $root = "/";
my $run_scripts = 1;
$run_scripts = 0 if (defined($in->{'noscripts'}) &&
$in->{'noscripts'} == 1);
local $temp = &transname();
my $rv = remove_cygwin_pkg($_[0], $temp, $root, $run_scripts);
if ($rv && &open_readfile(FILE, $temp)) {
my $out = join('', <FILE>);
close(FILE);
unlink($temp);
return "<pre>$out</pre>" if $rv;
}
return undef;
}
local $opts;
$opts .= $_[1]->{'nodeps'} ? "--nodeps " : "";
$opts .= $_[1]->{'noscripts'} ? "--noscripts " : "";
local $n = $_[2] ? "$_[0]-$_[2]" : $_[0];
local $qm = quotemeta($n);
local $out = &backquote_logged("rpm -e $opts $qm 2>&1");
if ($? || $out =~ /error:/) { return "<pre>$out</pre>"; }
return undef;
}
# delete_packages(&packages, [&options], &versions)
# Attempt to remove multiple packages at once
sub delete_packages
{
local $opts;
$opts .= $_[1]->{'nodeps'} ? "--nodeps " : "";
$opts .= $_[1]->{'noscripts'} ? "--noscripts " : "";
local $cmd = "rpm -e $opts";
local $i;
for($i=0; $i<@{$_[0]}; $i++) {
if ($_[2]->[$i]) {
$cmd .= " ".quotemeta($_[0]->[$i]."-".$_[2]->[$i]);
}
else {
$cmd .= " ".quotemeta($_[0]->[$i]);
}
}
local $out = &backquote_logged("$cmd 2>&1");
if ($? || $out =~ /error:/) { return "<pre>$out</pre>"; }
return undef;
}
sub package_system
{
my $text = "CYGWIN";
$text .= "/RPM" if $hasrpm;
return $text;
}
sub package_help
{
return "cygwin";
}
%etype = ( "5", $text{'rpm_md5'}, "S", $text{'rpm_fsize'},
"L", $text{'rpm_sym'}, "T", $text{'rpm_mtime'},
"D", $text{'rpm_dev'}, "U", $text{'rpm_user'},
"M", $text{'rpm_perm'}, "G", $text{'rpm_group'} );
$has_search_system = 1;
sub search_system_input
{
print "<input type=button onClick='window.ifield = document.forms[2].url; chooser = window.open(\"rpmfind.cgi\", \"chooser\", \"toolbar=no,menubar=no,scrollbars=yes,width=600,height=500\")' value=\"$text{'rpm_find'}\">";
}
# file, temp output file, root path
sub install_cygwin_src_pkg
{
my ($file, $temp, $root) = @_;
$root .= "/" if $root =~ /[^\/]$/;
$root .= "usr/src/";
&system_logged("mkdir -p $root > $temp 2>&1") if ! -d $root;
my $opts = "-jt";
$opts .= " -C $root";
my $pkg = $file;
$pkg =~ s/[_\-]\d.*//;
my $rv = &system_logged("tar $opts -f ".quotemeta($file).
" >>$temp 2>&1");
return $rv;
}
# file, temp output file, root path, run_scripts, replace pkgs, upgrade
sub install_cygwin_pkg
{
my ($file, $temp, $root, $run_scripts, $replace_pkgs, $upgrade) = @_;
$root .= "/" if $root =~ /[^\/]$/;
&system_logged("mkdir -p $root > $temp 2>&1") if ! -d $root;
my $opts = "-jxv";
$opts .= " -C $root";
my $pkg = $file;
$pkg =~ s/.*\/(.+?)[_\-]\d.*/$1/;
my $setupdir = "${root}etc/setup";
my $lstfile = "$setupdir/$pkg.lst";
#the only time we don't check for the same package currently installed
#is if the user specified to replace pkgs but not to upgrade
my @cygdata = ();
unless (! $upgrade && $replace_pkgs) {
#check to see if a package is already installed
@cygdata = cygwin_pkg_info($pkg);
if (@cygdata && $upgrade) {
remove_cygwin_pkg($cygdata[0], $temp, $root, $run_scripts);
}
}
if (@cygdata && ! $upgrade && ! $replace_pkgs) {
if (&open_tempfile(FILE, ">>$temp", 1)) {
&print_tempfile(FILE, &text('cygwin_pkgexists', $pkg) . "\n");
&close_tempfile(FILE);
}
return 1;
}
&system_logged("mkdir -p $setupdir") if ! -d $setupdir;
my $rv = &system_logged("tar $opts -f ".quotemeta($file).
" > $lstfile 2>>$temp");
if ($run_scripts && open(FILE, "<$lstfile")) {
#run postinstall scripts
while (<FILE>) {
if (/etc\/postinstall\/.*sh/) {
my $f = quotemeta($_);
$rv += &system_logged("sh $root$f >> $temp 2>&1");
$rv += &system_logged("mv -v $root$f $root$f.done>>$temp 2>&1");
}
}
close(FILE);
}
$rv += &system_logged("gzip -f $lstfile >>$temp 2>&1");
my $db = "$setupdir/installed.db";
$file =~ s/.*\///;
if (open(FILE, "<$db")) {
my @lines = <FILE>;
close(FILE);
#avoid windows security issues
&system_logged("chmod u+w $db >>$temp 2>&1") if ! -w $db;
&system_logged("chown $ENV{'USERNAME'} $db >>$temp 2>&1")
if ! -O $db;
&lock_file($db);
if (&open_tempfile(FILE, ">$db", 1)) {
#remove the package from the db if it already exists
@lines = grep {! /^$pkg /} @lines;
#add this package to the end.
push(@lines, "$pkg $file 0\n");
&print_tempfile(FILE, @lines);
&close_tempfile(FILE);
}
&unlock_file($db);
}
return $rv;
}
# pkg, temp output file, root path, run_scripts
sub remove_cygwin_pkg
{
my ($pkg, $temp, $root, $run_scripts) = @_;
$root .= "/" if $root =~ /[^\/]$/;
my $setupdir = "${root}etc/setup";
my $lstfile = "$setupdir/$pkg.lst.gz";
my $rv = 0;
my @cygdata = cygwin_pkg_info($pkg);
if (! @cygdata) {
if (&open_tempfile(FILE, ">$temp", 1)) {
&print_tempfile(FILE, "Could not find $pkg\n");
&close_tempfile(FILE);
}
#kludge: don't get rid of packages on which we depend
} elsif ($pkg =~ /^(perl|webmin|gzip|tar|bzip2|cygwin|ash)$/) {
if (&open_tempfile(FILE, ">$temp", 1)) {
&print_tempfile(FILE, "Not removing $pkg because of dependencies.\n");
&print_tempfile(FILE, "You'll have to force installation of the package.\n");
&close_tempfile(FILE);
}
#load in the list file
} elsif (! -f $lstfile || ! open(LST, "gunzip -c $lstfile |")) {
$rv = 1;
if (&open_tempfile(FILE, ">$temp")) {
&print_tempfile(FILE, "Could not open $lstfile\n");
&close_tempfile(FILE);
}
} else {
my @files = <LST>;
chomp(@files);
close(LST);
#run preremove scripts
if ($run_scripts) {
my @scripts = grep(/^etc\/preremove\/.*sh/, @files);
foreach (@scripts) {
my $f = quotemeta($_);
$rv += system_logged("sh $root$f >> $temp 2>&1");
$rv += system_logged("mv -v $root$f $root$f.done>>$temp 2>&1");
}
}
#remove all files except files in etc
foreach (reverse(@files)) {
next if /^etc\//;
if (-d $_) {
my $msg = &unlink_logged($_)? "" : $!;
$rv++ if $msg ne "";
} elsif (-f $_) {
my $msg = &unlink_logged($_)? "" : $!;
$rv++ if $msg ne "";
}
}
#run postremove scripts
if ($run_scripts) {
my @scripts = grep(/^etc\/postremove\/.*sh/, @files);
foreach (@scripts) {
my $f = quotemeta($_);
$rv += system_logged("sh $root$f >> $temp 2>&1");
$rv += system_logged("mv -v $root$f $root$f.done>>$temp 2>&1");
}
}
$rv += system_logged("rm -f $lstfile >>$temp 2>&1");
my $db = "$setupdir/installed.db";
lock_file($db);
if (&open_readfile(FILE, $db)) {
my @lines = <FILE>;
close(FILE);
if (&open_tempfile(FILE, ">$db")) {
#remove the package from the db
@lines = grep {! /^$pkg /} @lines;
&print_tempfile(FILE, @lines);
&close_tempfile(FILE);
}
}
unlock_file($db);
}
return $rv;
}
#returns: name, class, description, arch, version, vendor, installtime
sub cygwin_pkg_info
{
my ($pkg_name, $pkg_ver) = @_;
if (&open_readfile(DB, $db)) {
while (<DB>) {
if (/^([^\s]*)\s+([^\s]+)\s+(\d+)/) {
#TODO: classes, descriptions, vendor, installtime, arch
my ($name, $ver, $class, $desc) = ($1, $2, "cygwin", "");
next if $name ne $pkg_name;
$ver =~ s/.*?[_\-]([\d+].*)\.tar\..*/$1/;
next if defined($pkg_ver) && $pkg_ver ne $ver;
my ($arch, $vendor, $date) = ("i586", "cygwin", undef);
if (@_ = stat(&translate_filename("/etc/setup/$name.lst.gz"))) {
$date = make_date($_[9]);
}
close(DB);
return ($name, $class, $desc, $arch, $ver, $vendor, $date)
}
}
close(DB);
}
return ();
}
# Usable values in %file are path type user group mode size packages
sub get_file_info
{
my ($f) = @_;
my $predetected_error = "";
#check to make sure if it is a post install script that it was run
if ($f =~ /\/etc\/postinstall\/.*\.sh$/) {
if (-e $f) {
$predetected_error = $text{'cygwin_badpostscript'};
} else {
#automatically change postinstall script to be .done
#since it does not exist
$f =~ s%(/etc/postinstall/.*\.sh)$%$1.done%;
}
}
my %file;
my $real = &translate_filename($f);
$file{'path'} = $f;
if (! -l $real && ! -e $real) {
$file{'error'} = $text{'cygwin_fmissing'};
} elsif (-d $real) {
$file{'type'} = 1;
$file{'error'} = $predetected_error;
if (@_ = stat($real)) {
my @ent = getpwuid($_[4]);
$file{'user'} = (@ent && $ent[0] ne "????????")?
$ent[0] : $_[4];
@ent = getgrgid($_[5]);
$file{'group'} = (@ent && $ent[0] ne "????????")?
$ent[0] : $_[5];
$file{'size'} = $_[7];
$file{'mode'} = sprintf "%o", $_[2] & 07777;
}
} elsif (-l $real) {
$file{'type'} = 3;
if (@_ = lstat($real)) {
my @ent = getpwuid($_[4]);
$file{'user'} = (@ent && $ent[0] ne "????????")?
$ent[0] : $_[4];
@ent = getgrgid($_[5]);
$file{'group'} = (@ent && $ent[0] ne "????????")?
$ent[0] : $_[5];
$file{'size'} = $_[7];
$file{'mode'} = sprintf "%o", $_[2] & 07777;
if ($file{'link'} = readlink($real)) {
my $l = $file{'link'};
my $lreal = &translate_filename($l);
my $fb = $f; $fb =~ s/[^\/]*$//;
$l = $fb . $l if $l !~ /^\//;
if (! -l $lreal && ! -e $lreal) {
$file{'error'} = $text{'cygwin_lmissing'};
} else {
$file{'error'} = $predetected_error;
}
} else {
$file{'error'} = &text('cygwin_elread', $!);
}
} else {
$file{'error'} = &text('cygwin_elstat', $!);
}
} else {
#2 = special file; 0 = regular file
$file{'type'} = (-f $real)? 0 : 2;
if (@_ = stat($real)) {
my @ent = getpwuid($_[4]);
$file{'user'} = (@ent && $ent[0] ne "????????")?
$ent[0] : $_[4];
@ent = getgrgid($_[5]);
$file{'group'} = (@ent && $ent[0] ne "????????")?
$ent[0] : $_[5];
$file{'size'} = $_[7];
$file{'mode'} = sprintf "%o", $_[2] & 07777;
$file{'error'} = $predetected_error;
} else {
$file{'error'} = &text('cygwin_estat', $!);
}
}
return \%file;
}
1;
+355
View File
@@ -0,0 +1,355 @@
# debian-lib.pl
# Functions for debian DPKG package management
sub list_package_system_commands
{
return ("dpkg");
}
# list_packages([package]*)
# Fills the array %packages with a list of all packages
sub list_packages
{
local $i = 0;
local $arg = @_ ? join(" ", map { quotemeta($_) } @_) : "";
%packages = ( );
&open_execute_command(PKGINFO, "COLUMNS=1024 dpkg --list $arg", 1, 1);
while(<PKGINFO>) {
next if (/^\|/ || /^\+/);
if (/^[uirph]i..(\S+)\s+(\S+)\s+(.*)/) {
$packages{$i,'name'} = $1;
$packages{$i,'class'} = &alphabet_name($1);
$packages{$i,'version'} = $2;
$packages{$i,'desc'} = $3;
if ($packages{$i,'version'} =~ /^(\d+):(.*)$/) {
$packages{$i,'epoch'} = $1;
$packages{$i,'version'} = $2;
}
if ($packages{$i,'name'} =~ /^(\S+):(\S+)$/) {
$packages{$i,'name'} = $1;
$packages{$i,'arch'} = $2;
}
if ($packages{$i,'desc'} =~ /^(all|amd64|x86|arm)\s+(\S.*)/) {
$packages{$i,'arch'} = $1;
$packages{$i,'desc'} = $2;
}
$i++;
}
}
close(PKGINFO);
return $i;
}
sub alphabet_name
{
return lc($_[0]) =~ /^[a-e]/ ? "A-E" :
lc($_[0]) =~ /^[f-j]/ ? "F-J" :
lc($_[0]) =~ /^[k-o]/ ? "K-O" :
lc($_[0]) =~ /^[p-t]/ ? "P-T" :
lc($_[0]) =~ /^[u-z]/ ? "U-Z" : "Other";
}
# package_info(package, [version])
# Returns an array of package information in the order
# name, class, description, arch, version, vendor, installtime
sub package_info
{
local ($pkg, $ver) = @_;
local $qm = quotemeta($pkg);
# First check if it is really installed, and not just known to the package
# system in some way
local $out = &backquote_command("dpkg --list $qm 2>&1", 1);
local @lines = split(/\r?\n/, $out);
if ($lines[$#lines] !~ /^.[ih]/) {
return ( );
}
# Get full status
local $out;
if (&has_command("apt-cache")) {
$qm .= "=*".quotemeta($ver) if ($ver);
$out = &backquote_command("apt-cache show $qm 2>&1", 1);
$out =~ s/[\0-\177]*\r?\n\r?\n(Package:)/\\1/; # remove available ver
}
else {
$out = &backquote_command("dpkg --print-avail $qm 2>&1", 1);
}
return () if ($? || $out =~ /Package .* is not available/i);
# Set name and class
local @rv = ( $_[0], &alphabet_name($_[0]) );
# Get description
push(@rv, $out =~ /Description(-en)?:\s+((.*\n)(\s+.*\n)*)/i
? $2
: $text{'debian_unknown'});
# Get architecture
push(@rv, $out =~ /Architecture:\s+(\S+)/i
? $1
: $text{'debian_unknown'});
my $arch = $1;
# Get version
push(@rv, $out =~ /Version:\s+(\S+)/i
? $1
: $text{'debian_unknown'});
# Get maintainer
push(@rv, $out =~ /Maintainer:\s+(.*)/i
? &html_escape($1)
: $text{'debian_unknown'});
# Get install time from the package info file
my ($path) = grep { -e $_ } $arch
? ("/var/lib/dpkg/info/$pkg:$arch.list", "/var/lib/dpkg/info/$pkg.list")
: ("/var/lib/dpkg/info/$pkg.list"); # prefer multi-arch
my $inst_epoch = $path ? (stat($path))[9] : undef;
push(@rv, $inst_epoch ? &make_date($inst_epoch) : undef);
# Get homepage
push(@rv, $out =~ /Homepage:\s+(.*)/i ? $1 : undef);
# Return info
return @rv;
}
# virtual_package_info(package)
# Returns an array of package information for a virtual package, usually called
# if "package_info" returns nothing.
sub virtual_package_info
{
my ($pkg) = @_;
my $qpkg = quotemeta($pkg);
my $apt_cache_cmd = &has_command("apt-cache");
return ( ) if (!$apt_cache_cmd);
my $out = &backquote_command("$apt_cache_cmd showpkg $qpkg 2>&1", 1);
# Get the package that provides this virtual package
my ($vpkg);
if ($out =~ /Reverse Provides:\s*(\S+\s+\S+)/) {
my ($rpkg, $rver) = split(/\s+/, $1, 2);
$vpkg = $rpkg;
$qvpkg = quotemeta($vpkg)."=".quotemeta($rver);
}
return ( ) if (!$vpkg);
# Get full status
$out = &backquote_command("$apt_cache_cmd show $qvpkg 2>&1", 1);
$out =~ s/[\0-\177]*\r?\n\r?\n(Package:)/\\1/; # remove available ver
return () if ($? || $out =~ /Package .* is not available/i);
local @rv = ( $vpkg, &alphabet_name($vpkg) );
push(@rv, $out =~ /Description(-en)?:\s+((.*\n)(\s+.*\n)*)/i ? $2
: $text{'debian_unknown'});
push(@rv, $out =~ /Architecture:\s+(\S+)/i ? $1 : $text{'debian_unknown'});
push(@rv, $out =~ /Version:\s+(\S+)/i ? $1 : $text{'debian_unknown'});
push(@rv, $out =~ /Maintainer:\s+(.*)/i ? &html_escape($1)
: $text{'debian_unknown'});
push(@rv, $text{'debian_unknown'});
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 = 0;
local $file;
local $qm = quotemeta($_[0]);
&open_execute_command(PKGINFO, "dpkg --listfiles $qm", 1, 1);
while($file = <PKGINFO>) {
$file =~ s/\r|\n//g;
next if ($file !~ /^\/[^\.]/);
local @st = stat($file);
$files{$i,'path'} = $file;
$files{$i,'type'} = -l $file ? 3 :
-d $file ? 1 : 0;
$files{$i,'user'} = getpwuid($st[4]);
$files{$i,'group'} = getgrgid($st[5]);
$files{$i,'mode'} = sprintf "%o", $st[2] & 07777;
$files{$i,'size'} = $st[7];
$files{$i,'link'} = readlink($file);
$i++;
}
return $i;
}
# package_files(package)
# Returns a list of all files in some package
sub package_files
{
local ($pkg) = @_;
local $qn = quotemeta($pkg);
local @rv;
&open_execute_command(RPM, "dpkg --listfiles $qn", 1, 1);
while(<RPM>) {
s/\r|\n//g;
push(@rv, $_);
}
close(RPM);
return @rv;
}
# 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 $qm = quotemeta($_[0]);
local $out = &backquote_command("dpkg --search $qm 2>&1", 1);
return 0 if ($out =~ /not\s+found|no\s+path\s+found/i);
$out =~ s/:\s+\S+\n$//;
local @pkgin = split(/[\s,]+/, $out);
local $real = &translate_filename($_[0]);
local @st = stat($real);
$file{'path'} = $_[0];
$file{'type'} = -l $real ? 3 :
-d $real ? 1 : 0;
$file{'user'} = getpwuid($st[4]);
$file{'group'} = getgrgid($st[5]);
$file{'mode'} = sprintf "%o", $st[2] & 07777;
$file{'size'} = $st[7];
$file{'link'} = readlink($real);
$file{'packages'} = join(" ", @pkgin);
return 1;
}
# is_package(file)
sub is_package
{
local $qm = quotemeta($_[0]);
local $out = &backquote_command("dpkg --info $qm 2>&1", 1);
return $? || $out !~ /Package:/ ? 0 : 1;
}
# file_packages(file)
# Returns a list of all packages in the given file, in the form
# package description
sub file_packages
{
local $qm = quotemeta($_[0]);
local $out = &backquote_command("dpkg --info $qm 2>&1", 1);
local $name;
if ($out =~ /Package:\s+(\S+)/i && ($name=$1) &&
$out =~ /Description:\s+(.*)/i) {
return ( "$name $1" );
}
return ();
}
# install_options(file, package)
# Outputs HTML for choosing install options
sub install_options
{
print &ui_table_row($text{'debian_depends'},
&ui_yesno_radio("depends", 0));
print &ui_table_row($text{'debian_conflicts'},
&ui_yesno_radio("conflicts", 0));
print &ui_table_row($text{'debian_overwrite'},
&ui_yesno_radio("overwrite", 0));
print &ui_table_row($text{'debian_downgrade'},
&ui_yesno_radio("downgrade", 0));
}
# install_package(file, package)
# Installs the package in the given file, with options from %in
sub install_package
{
local $in = $_[2] ? $_[2] : \%in;
local $args = ($in->{'depends'} ? " --force-depends" : "").
($in->{'conflicts'} ? " --force-conflicts" : "").
($in->{'overwrite'} ? " --force-overwrite" : "").
($in->{'downgrade'} ? " --force-downgrade" : "");
local $qm = quotemeta($_[0]);
$ENV{'UCF_FORCE_CONFFOLD'} = 'YES';
$ENV{'DEBIAN_FRONTEND'} = 'noninteractive';
local $out = &backquote_logged("dpkg --install $args $qm 2>&1 </dev/null");
if ($?) {
return "<pre>$out</pre>";
}
return undef;
}
# delete_options(package)
# Outputs HTML for package uninstall options
sub delete_options
{
print "<b>$text{'delete_purge'}</b>\n";
print &ui_yesno_radio("purge", 0),"<br>\n";
if ($update_system eq "apt") {
print "<b>$text{'delete_depstoo'}</b>\n";
print &ui_yesno_radio("depstoo", 0),"<br>\n";
}
}
# delete_package(package, [&options], version)
# Totally remove some package
sub delete_package
{
local $qm = quotemeta($_[0]);
$ENV{'DEBIAN_FRONTEND'} = 'noninteractive';
local $out;
if ($_[1]->{'depstoo'}) {
# Use apt-get
local $flag = $_[1]->{'purge'} ? "--purge" : "";
$out = &backquote_logged("apt-get -y autoremove $flag $qm 2>&1 </dev/null");
}
else {
# Use dpkg command
local $flag = $_[1]->{'purge'} ? "--purge" : "--remove";
$out = &backquote_logged("dpkg $flag $qm 2>&1 </dev/null");
}
if ($? || $out =~ /which isn.t installed/i) {
return "<pre>$out</pre>";
}
return undef;
}
# package_dependencies(name, [version])
# Returns a list of packages that this one depends on, as hash refs
sub package_dependencies
{
my ($pkg, $ver) = @_;
my $out = &backquote_command(
"apt-cache show ".quotemeta($pkg)." 2>/dev/null");
return () if ($?);
$out =~ /\nDepends:\s+(.*)/ || return ();
my @rv;
foreach my $w (split(/,\s+/, $1)) {
if ($w =~ /^(\S+)\s+\(([<>=]+)\s+(\S+)\)/) {
# Depends on a specific version
push(@rv, { 'package' => $1,
'compare' => $2,
'version' => $3 });
}
elsif ($w =~ /^(\S+)$/) {
# Depends on some package
push(@rv, { 'package' => $1 });
}
elsif ($w =~ /^(\S+)\s+\|/) {
# Depends on one of several packages, but just show the first
push(@rv, { 'package' => $1 });
}
}
return @rv;
}
sub package_system
{
return $text{'debian_manager'};
}
sub package_help
{
return "dpkg";
}
1;
+11
View File
@@ -0,0 +1,11 @@
#!/usr/local/bin/perl
# delete_file.cgi
# Delete a downloaded package that is no longer needed
require './software-lib.pl';
&ReadParse();
my $tmp_base = $gconfig{'tempdir'} || &default_webmin_temp_dir();
&is_under_directory($tmp_base, $in{'file'}) || &error($text{'delete_efile'});
unlink($in{'file'}) if (!&is_readonly_mode());
&redirect("");
+65
View File
@@ -0,0 +1,65 @@
#!/usr/local/bin/perl
# delete_pack.cgi
# Ask if the user wants to delete a package, and if so do it
require './software-lib.pl';
&ReadParse();
$p = $in{'package'};
$v = $in{'version'};
&error_setup(&text('delete_err', $p));
(@pinfo = &package_info($p, $v)) ||
&error(&text('delete_epack', $p));
if ($in{'sure'}) {
# do the deletion
&list_packages($p);
if ($error = &delete_package($p, \%in, $v)) {
&ui_print_header(undef, $text{'delete_title'}, "", "delete");
print &text('delete_err', "<tt>$p</tt> :<br>$error"),"\n";
&ui_print_footer(
"edit_pack.cgi?search=$in{'search'}&package=".&urlize($p).
"&version=".&urlize($v), $text{'edit_return'});
return;
}
&webmin_log("delete", "package", $p, { 'desc' => $packages{0,'desc'} });
if ($in{'search'}) {
&redirect("search.cgi?search=$in{'search'}");
}
else {
&redirect("");
}
}
else {
&ui_print_header(undef, $text{'delete_title'}, "", "delete");
# Sum up files
$n = &check_files($p, $v);
$sz = 0;
for($i=0; $i<$n; $i++) {
if ($files{$i,'type'} == 0) { $sz += $files{$i,'size'}; }
}
print "<center>\n";
if ($n) {
print &text('delete_rusure', "<tt>$p</tt>", $n, &nice_size($sz)),"<p>\n";
}
else {
print &text('delete_rusure2', "<tt>$p</tt>"),"<p>\n";
}
# Ask if the user is sure..
print &ui_form_start("delete_pack.cgi");
print &ui_hidden("package", $p);
print &ui_hidden("version", $v);
print &ui_hidden("sure", 1);
print &ui_hidden("search", $in{'search'});
print &ui_submit($text{'delete_ok'}),"<p>\n";
if (defined(&delete_options)) {
&delete_options($p);
}
print &ui_form_end(),"</center>\n";
&ui_print_footer(
"edit_pack.cgi?search=$in{'search'}&package=".&urlize($p).
"&version=".&urlize($v), $text{'edit_return'});
}
+71
View File
@@ -0,0 +1,71 @@
#!/usr/local/bin/perl
# delete_packs.cgi
# Ask if the user wants to delete multiple packages, and if so do it
# XXX logging
require './software-lib.pl';
&ReadParse();
&error_setup($text{'deletes_err'});
foreach $d (split(/\0/, $in{'del'})) {
local ($p, $v) = split(/\s/, $d);
local @pinfo;
(@pinfo = &package_info($p, $v)) ||
&error(&text('delete_epack', $p));
push(@packs, $p);
push(@vers, $v);
push(@infos, \@pinfo);
}
@packs || &error($text{'deletes_enone'});
&ui_print_header(undef, $text{'deletes_title'}, "", "delete");
if ($in{'sure'}) {
# do the deletion
print "\n";
if (defined(&delete_packages)) {
# Can just use one function
print &text('deletes_desc', "<tt>".join(" ", @packs)."</tt>"),
"\n";
$error = &delete_packages(\@packs, \%in, \@vers);
if ($error) {
print &text('deletes_failed2', $error),"\n";
}
else {
print "$text{'deletes_success2'}\n";
}
}
else {
# Need to use a loop
for($i=0; $i<@packs; $i++) {
$error = &delete_package($packs[$i], \%in, $vers[$i]);
if ($error) {
print &text('deletes_failed1', "<tt>$packs[$i]</tt>", $error),"<br>\n";
}
else {
print &text('deletes_success1', "<tt>$packs[$i]</tt>"),"<br>\n";
}
}
}
&webmin_log("deletes", "package", undef, { 'packs' => \@packs });
}
else {
# Ask if the user is sure..
print "<center>\n";
print &text('deletes_rusure', "<tt>".join(" ", @packs)."</tt>"),
"<p>\n";
print &ui_form_start("delete_packs.cgi", "post");
foreach $d (split(/\0/, $in{'del'})) {
print &ui_hidden("del", $d);
}
print &ui_hidden("sure", 1);
print &ui_hidden("search", $in{'search'});
print &ui_submit($text{'deletes_ok'}),"<p>\n";
if (defined(&delete_options)) {
&delete_options($packs[0]);
}
print &ui_form_end(),"</center>\n";
}
&ui_print_footer("search.cgi?search=$in{'search'}", $text{'search_return'});
+103
View File
@@ -0,0 +1,103 @@
#!/usr/local/bin/perl
# do_install.cgi
# Do the actual installation of a package from a file
require './software-lib.pl';
&ReadParse();
&error_setup(&text('do_err', $in{'package'}));
if ($show_install_progress) {
&ui_print_unbuffered_header(undef, $text{'do_title'}, "");
}
else {
&ui_print_header(undef, $text{'do_title'}, "");
}
# Save this CGI from being killed by a webmin or apache upgrade
$SIG{'TERM'} = 'IGNORE';
$SIG{'PIPE'} = 'IGNORE';
@packages = &file_packages($in{'file'});
if (defined(&install_packages) && @packages > 1) {
# Can install everything in one hit
&clean_environment();
$error = &install_packages($in{'file'}, \%in);
&reset_environment();
if ($error) { &install_error($error); }
if ($in{'need_unlink'}) { &unlink_file($in{'file'}); }
foreach $p (@packages) {
# Display package details
($package, $desc) = split(/\s+/, $p, 2);
@pinfo = &show_package_info($package);
# Display new files
@grid = ( );
$n = &check_files($package);
for($i=0; $i<$n; $i++) {
push(@grid, &html_escape($files{$i,'path'}));
}
print &ui_grid_table(\@grid, 2, 100, undef, undef,
$text{'do_files'});
&list_packages($package);
&webmin_log('install', 'package', $package,
{ 'desc' => $packages{0,'desc'},
'class' => $packages{0,'class'} });
}
}
else {
# Must install and show one by one
foreach $p (@packages) {
# attempt to install
print &ui_hr() if ($p ne $packages[0]);
($package, $desc) = split(/\s+/, $p, 2);
&clean_environment();
if ($show_install_progress) {
print "<pre>\n";
$error = &install_package(
$in{'file'}, &html_escape($package), \%in, 1);
print "</pre>\n";
}
else {
$error = &install_package(
$in{'file'}, &html_escape($package), \%in);
}
&reset_environment();
if ($error) { &install_error($error); }
if ($in{'need_unlink'}) { &unlink_file($in{'file'}); }
# display information
@pinfo = &show_package_info($package);
# Show files in package, if possible
$n = &check_files($package);
if ($n) {
@grid = ( );
for($i=0; $i<$n; $i++) {
push(@grid, &html_escape($files{$i,'path'}));
}
print &ui_grid_table(\@grid, 2, 100, undef, undef,
$text{'do_files'});
}
&list_packages($package);
&webmin_log('install', 'package', $package,
{ 'desc' => $packages{0,'desc'},
'class' => $packages{0,'class'} });
}
}
&ui_print_footer("", $text{'index_return'});
sub install_error
{
print "<b>",&text('do_efailed', @{[&html_escape($error)]}),"</b><p>\n";
print $text{'do_efailedmsg1'},"<p>\n";
if ($in{'need_unlink'}) {
print &text('do_efailedmsg2',
"delete_file.cgi?file=".
&urlize($in{'file'})),"<p>\n";
}
&ui_print_footer("", $text{'index_return'});
exit;
}
+44
View File
@@ -0,0 +1,44 @@
#!/usr/local/bin/perl
# edit_pack.cgi
# Displays the details of an existing package, with links to uninstall and
# other options
require './software-lib.pl';
&ReadParse();
@pinfo = &package_info($in{'package'}, $in{'version'});
$pinfo[0] || &error($text{'edit_egone'});
&ui_print_header(undef, $text{'edit_title'}, "", "edit_pack");
@pinfo = &show_package_info($in{'package'}, $in{'version'}, 1);
print &ui_buttons_start();
# Show button to list files, if supported
if (!$pinfo[8]) {
print &ui_buttons_row("list_pack.cgi",
$text{'edit_list'},
$text{'edit_listdesc'},
&ui_hidden("package", $pinfo[0]).
&ui_hidden("version", $pinfo[4]).
&ui_hidden("search", $in{'search'}));
}
# Show button to un-install (if possible)
if (!$pinfo[7]) {
print &ui_buttons_row("delete_pack.cgi",
$text{'edit_uninst'},
$text{'edit_uninstdesc'},
&ui_hidden("package", $pinfo[0]).
&ui_hidden("version", $pinfo[4]).
&ui_hidden("search", $in{'search'}));
}
print &ui_buttons_end();
if ($in{'search'}) {
&ui_print_footer("search.cgi?search=$in{'search'}", $text{'search_return'});
}
else {
&ui_print_footer("tree.cgi#$pinfo[1]", $text{'index_treturn'});
}
+321
View File
@@ -0,0 +1,321 @@
# emerge-lib.pl
# Functions for gentoo package management
chop($system_arch = `uname -m`);
$pkg_dir = "/var/db/pkg";
$portage_bin = "/usr/lib/portage/bin";
$ENV{'TERM'} = "dumb";
$package_list_binary = $package_list_command = "$portage_bin/pkglist";
if (!-x $package_list_binary) {
$package_list_binary = &has_command("qlist");
$package_list_command = $package_list_binary." --nocolor -Iv";
}
sub list_package_system_commands
{
return ( $package_list_binary || "pkglist" );
}
sub list_update_system_commands
{
return ("emerge");
}
# list_packages([package]*)
# Fills the array %packages with all or listed packages
sub list_packages
{
local $i = 0;
%packages = ( );
&open_execute_command(LIST, $package_list_command, 1, 1);
while(<LIST>) {
if (/^([^\/]+)\/([^0-9]+)-(\d\S+)$/ &&
!@_ || &indexof($2, @_) >= 0) {
$packages{$i,'name'} = $2;
$packages{$i,'class'} = $1;
$packages{$i,'version'} = $3;
&open_readfile(BUILD, "$pkg_dir/$1/$2-$3/$2-$3.ebuild");
while(<BUILD>) {
if (/DESCRIPTION="([^"]+)"/ || /DESCRIPTION='([^']+)'/) {
$packages{$i,'desc'} = $1;
last;
}
}
close(BUILD);
$i++;
}
}
return $i;
}
# package_search(string, [allavailable])
# Searches the package database for packages matching some string and puts
# them into %packages
sub package_search
{
local $n = 0;
local $qm = quotemeta($_[0]);
&open_execute_command(SEARCH, "emerge search $qm", 1, 1);
while(<SEARCH>) {
s/\r|\n//g;
s/\033[^m]+m//g;
if (/^\*\s+([^\/]+)\/(\S+)/) {
$packages{$n,'name'} = $2;
$packages{$n,'class'} = $1;
$packages{$n,'missing'} = 0;
}
elsif (/version\s+Available:\s+(\S+)/i) {
$packages{$n,'version'} = $1;
}
elsif (/version\s+Installed:\s+\[\s+Not/i && !$_[1]) {
$packages{$n,'missing'} = 1;
}
elsif (/\s+Description:\s*(.*)/i) {
$packages{$n,'desc'} = $1;
local $nl = <SEARCH>;
chop($nl);
if ($nl =~ /\S/) {
$packages{$n,'desc'} .= " " if ($packages{$n,'desc'});
$packages{$n,'desc'} .= $nl;
}
$n++ if (!$packages{$n,'missing'} || $_[1]);
}
}
close(SEARCH);
return $n;
}
# package_info(package)
# Returns an array of package information in the order
# name, class, description, arch, version, vendor, installtime
sub package_info
{
local %packages;
local $n = &list_packages($_[0]);
$n || return ();
local @st = stat("$pkg_dir/$packages{0,'class'}/$packages{0,'name'}-$packages{0,'version'}");
return ( $packages{0,'name'}, $packages{0,'class'}, $packages{0,'desc'},
$system_arch, $packages{0,'version'}, "Gentoo", &make_date($st[9]) );
}
# virtual_package_info(package)
# Returns an array of package information for a virtual package, usually called
# if "package_info" returns nothing.
sub virtual_package_info
{
return ( );
}
# is_package(file)
# Check if some file is a package file
sub is_package
{
local $qm = quotemeta($_[0]);
local $out = &backquote_command("emerge --pretend $qm 2>&1", 1);
return $? ? 0 : 1;
}
# file_packages(file)
# Returns a list of all packages in the given file, in the form
# package description
sub file_packages
{
local @rv;
local $qm = quotemeta($_[0]);
&open_execute_command(EMERGE, "emerge --pretend $qm", 1, 1);
while(<EMERGE>) {
s/\r|\n//g;
s/\033[^m]+m//g;
if (/\s+[NRU]\s+\]\s+([^\/]+)\/([^0-9]+)\-(\d\S+)/) {
push(@rv, $2);
}
}
close(EMERGE);
return @rv;
}
# install_options(file, package)
# Outputs HTML for choosing install options for some package
sub install_options
{
print &ui_table_row($text{'emerge_noreplace'},
&ui_radio("noreplace", 0, [ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]));
print &ui_table_row($text{'emerge_onlydeps'},
&ui_yesno_radio("onlydeps", 0));
}
$show_install_progress = 1;
# install_package(file, package, [&inputs], [show])
# Install the given package from the given file, using options from %in
sub install_package
{
local $file = $_[0];
local $in = $_[2] ? $_[2] : \%in;
local $cmd = "emerge";
$cmd .= " --noreplace" if ($in{'noreplace'});
$cmd .= " --onlydeps" if ($in{'onlydeps'});
$cmd .= " ".quotemeta($_[1]);
if ($_[3]) {
&open_execute_command(OUT, "$cmd 2>&1", 1);
while(<OUT>) {
print &html_escape($_);
}
close(OUT);
return $? ? "Emerge error" : undef;
}
else {
local $out;
&open_execute_command(OUT, "$cmd 2>&1 | tail -10", 1);
while(<OUT>) {
$out .= $_;
}
close(OUT);
return $? ? "<pre>$out</pre>" : undef;
}
}
# 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 size error
sub check_files
{
local $i = 0;
local (@files, %filesmap);
local %packages;
&list_packages($_[0]);
&open_readfile(CONTENTS, "$pkg_dir/$packages{0,'class'}/$packages{0,'name'}-$packages{0,'version'}/CONTENTS");
while(<CONTENTS>) {
s/\r|\n//g;
local @l = split(/\s+/);
$files{$i,'path'} = $l[1];
$files{$i,'type'} = $l[0] eq 'dir' ? 1 :
$l[0] eq 'sym' ? 3 : 0;
local $real = &translate_filename($l[1]);
local @st = stat($real);
$files{$i,'user'} = getpwuid($st[4]);
$files{$i,'group'} = getgrgid($st[5]);
$files{$i,'size'} = $st[7];
if (!-e $l[1]) {
$files{$i,'error'} = "Does not exist";
}
elsif ($l[0] eq 'sym') {
$files{$i,'link'} = $l[3];
local $lnk = readlink($real);
$files{$i,'error'} = "Incorrect link" if ($l[3] ne $lnk);
}
elsif ($l[0] eq 'obj') {
push(@files, $l[1]);
$filesmap{$l[1]} = $i;
$files{$i,'md5'} = $l[2];
}
$i++;
}
close(CONTENTS);
if (&has_command("md5sum")) {
&open_execute_command(MD5, "md5sum ".join(" ", @files), 1, 1);
while(<MD5>) {
local ($md, $fn) = split(/\s+/);
local $n = $filesmap{$fn};
if ($md ne $files{$n,'md5'}) {
$files{$n,'error'} = "Checksum failed";
}
}
close(MD5);
}
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 ($cf, $type, @packs);
local $real_dir = &translate_filename($pkg_dir);
while($cf = <$real_dir/*/*/CONTENTS>) {
open(FILE, "<".$cf);
while(<FILE>) {
local @l = split(/\s+/);
if ($l[1] eq $_[0]) {
# Found it!
$cf =~ /\/([^0-9\/]+)-(\d[^\s\/]+)\/CONTENTS$/;
push(@packs, $1);
$type = $l[0] if (!$type);
}
}
close(FILE);
}
return 0 if (!@packs);
local $real = &translate_filename($_[0]);
local @st = stat($real);
$file{'packages'} = join(' ', @packs);
$file{'path'} = $_[0];
$file{'user'} = getpwuid($st[4]);
$file{'group'} = getgrgid($st[5]);
$file{'mode'} = sprintf "%o", $st[2] & 07777;
$file{'size'} = $st[7];
$file{'link'} = readlink($real);
$file{'type'} = $type eq 'dir' ? 1 :
$type eq 'sym' ? 3 : 0;
return 1;
}
# delete_package(package, [&options])
# Attempt to remove some package
sub delete_package
{
local $out = &backquote_logged("emerge -u ".quotemeta($_[0])." 2>&1");
return $? ? "<pre>$out</pre>" : undef;
}
sub package_system
{
return "Gentoo Ebuild";
}
sub package_help
{
return "emerge";
}
$has_update_system = 1;
# update_system_input()
# Returns HTML for entering a package to install
sub update_system_input
{
return "$text{'emerge_input'} <input name=update size=20> <input type=button onClick='window.ifield = form.update; chooser = window.open(\"../$module_name/emerge_find.cgi\", \"chooser\", \"toolbar=no,menubar=no,scrollbars=yes,width=600,height=500\")' value=\"$text{'emerge_find'}\">";
}
# update_system_install([package])
# Install some package with emerge
sub update_system_install
{
local $update = $_[0] || $in{'update'};
local $cmd = "emerge ".quotemeta($update);
local @rv;
print &text('emerge_install', "<tt>$cmd</tt>"),"\n";
print "<pre data-installer>\n";
&additional_log('exec', undef, $cmd);
&open_execute_command(CMD, "$cmd 2>&1 </dev/null", 1);
while(<CMD>) {
print &html_escape($_);
if (/^\>\>\>\s+([^\/]+)\/([^0-9]+)-(\d\S+)\s+merged\./i) {
push(@rv, $2);
}
}
close(CMD);
print "</pre>\n";
if ($?) { print "$text{'emerge_failed'}<p>\n"; }
else { print "$text{'emerge_ok'}<p>\n"; }
return @rv;
}
1;
+78
View File
@@ -0,0 +1,78 @@
#!/usr/local/bin/perl
# file_info.cgi
# Display information about a file owned by the package management system
require './software-lib.pl';
&ReadParse();
$f = $in{'file'};
&ui_print_header(undef, $text{'file_title'}, "", "file_info");
$f =~ s/\/$//;
if ($f !~ /^\//) {
# if the filename is not absolute, look for it
foreach $p (split(/:/, $ENV{'PATH'})) {
last if (&installed_file("$p/$f") && %file);
}
}
else {
# absolute path.. must exist in DB
&installed_file($f);
}
if (!%file) {
print "<b>",&text('file_notfound',
"<tt>".&html_escape($f)."</tt>"),"</b><p>\n";
}
else {
# display file info
$nc = "width=10% nowrap";
print &ui_table_start($text{'file_title'}, "width=100%", 4);
print &ui_table_row($text{'file_path'},
"<tt>".&html_escape($file{'path'})."</tt>", 3);
print &ui_table_row($text{'file_type'},
$type_map[$file{'type'}]);
if ($file{'type'} != 3 && $file{'type'} != 4) {
print &ui_table_row($text{'file_perms'}, $file{'mode'});
print &ui_table_row($text{'file_owner'}, $file{'user'});
print &ui_table_row($text{'file_group'}, $file{'group'});
if ($file{'type'} == 0) {
print &ui_table_row($text{'file_size'}, $file{'size'});
}
}
else {
print &ui_table_row($text{'file_link'},
"<tt>".&html_escape($file{'link'})."</tt>", 3);
}
print &ui_table_end();
# Show packages containing the file (usually only one)
print &ui_columns_start([ $text{'file_pack'},
$text{'file_class'},
$text{'file_desc'} ], 100);
@pkgs = split(/\s+/, $file{'packages'});
@vers = split(/\s+/, $file{'versions'});
$n = &list_packages(@pkgs);
for($j=0; $j<@pkgs; $j++) {
for($i=0; $i<$n; $i++) {
next if ($vers[$i] &&
$packages{$i,'version'} ne $vers[$j] ||
$packages{$i,'name'} ne $pkgs[$j]);
local @cols;
push(@cols, &ui_link("edit_pack.cgi?package=".
&urlize($pkgs[$j])."&version=".&urlize($vers[$j]), $pkgs[$j]) );
$c = $packages{$i,'class'};
push(@cols, $c || $text{'file_none'});
push(@cols, $packages{$i,'desc'});
print &ui_columns_row(\@cols);
}
}
print &ui_columns_end();
}
&ui_print_footer("", $text{'index_return'});
+69
View File
@@ -0,0 +1,69 @@
#!/usr/local/bin/perl
# Show a form in a popup window for selecting a package from the update system
require './software-lib.pl';
&ReadParse();
&popup_header($text{'find_title'});
print <<EOF;
<script>
function sel(m)
{
window.opener.ifield.value = m;
window.close();
return false;
}
</script>
EOF
# Show form for searching
print &ui_form_start("find.cgi");
print &ui_submit($text{'find_search'}),"\n";
print &ui_textbox("search", $in{'search'}, 20),"\n";
print &ui_form_end();
# Show results, if any
$search = $in{'search'};
if (defined($search)) {
if (!$search) {
# List them all
@avail = &update_system_available();
}
elsif (defined(&update_system_search)) {
# Call the search function
@avail = &update_system_search($search);
}
else {
# Scan through list manually
@avail = &update_system_available();
@avail = grep { $_->{'name'} =~ /\Q$search\E/i ||
$_->{'desc'} =~ /\Q$search\E/i } @avail;
}
@avail = sort { lc($a->{'name'}) cmp lc($b->{'name'}) } @avail;
if (@avail) {
foreach $a (@avail) {
$hasdesc++ if ($a->{'desc'});
$hasver++ if ($a->{'version'});
}
print &ui_columns_start(
[ $text{'find_name'},
$hasver ? ($text{'find_version'}) : ( ),
$hasdesc ? ($text{'find_desc'}) : ( ) ], "100%");
foreach $a (@avail) {
$sel = $a->{'select'} || $a->{'name'};
$epoch = $a->{'epoch'} ? "$a->{'epoch'}:" : "";
print &ui_columns_row(
[ &ui_link("#", $a->{'name'}, undef, "onClick='sel(\"$sel\");'"),
$hasver ? ($epoch.$a->{'version'}) : ( ),
$hasdesc ? ($a->{'desc'}) : ( ) ]);
}
print &ui_columns_end();
}
else {
print "<b>$text{'find_none'}</b><p>\n";
}
}
&popup_footer();
+351
View File
@@ -0,0 +1,351 @@
# bsd-lib.pl
# Functions for FreeBSD package management
use POSIX;
chop($system_arch = `uname -m`);
if (&use_pkg_ng()) {
# check whether the new pkg manager is available and use that.
$pkg_info = "pkg info";
$pkg_add = "pkg add";
$pkg_delete = "pkg delete";
}
else {
# If not, default to the previous pkg manager tools
$pkg_info = "pkg_info";
$pkg_add = "pkg_add";
$pkg_delete = "pkg_delete";
}
$package_dir = "/var/db/pkg";
sub use_pkg_ng
{
return 0 if (!-x "/usr/sbin/pkg");
local @lines = split(/\n/, &backquote_command(
"/usr/sbin/pkg info 2>/dev/null </dev/null"));
return @lines > 1 ? 1 : 0;
}
sub list_package_system_commands
{
return ($pkg_info, $pkg_add);
}
# list_packages([package]*)
# Fills the array %packages with a list of all packages
sub list_packages
{
local $i = 0;
local $arg = @_ ? join(" ", map { quotemeta($_) } @_) : "-a";
%packages = ( );
&open_execute_command(PKGINFO, "$pkg_info -I $arg", 1, 1);
while(<PKGINFO>) {
if (/^(\S+)\-(\d\S+)\s+(.*)/) {
$packages{$i,'name'} = $1;
$packages{$i,'version'} = $2;
$packages{$i,'class'} = "";
$packages{$i,'desc'} = $3;
$i++;
}
}
close(PKGINFO);
return $i;
}
# package_info(package, [version])
# Returns an array of package information in the order
# name, class, description, arch, version, vendor, installtime
sub package_info
{
local ($name, $ver) = @_;
local $qm = quotemeta($name.($ver ? '='.$ver : '>=0'));
local $out = &backquote_command("$pkg_info $qm 2>&1", 1);
return () if ($?);
local @rv = ( $name );
push(@rv, "");
push(@rv, $out =~ /Description:\n([\0-\177]*\S)/i ? $1 : $text{'bsd_unknown'});
push(@rv, $system_arch);
push(@rv, $out =~ /Information\s+for\s+(\S+)\-(\d\S+)/ ? $2 : $ver);
push(@rv, "FreeBSD");
local @st = stat(&translate_filename("$package_dir/$name-$ver"));
push(@rv, @st ? ctime($st[9]) : $text{'bsd_unknown'});
return @rv;
}
# virtual_package_info(package)
# Returns an array of package information for a virtual package, usually called
# if "package_info" returns nothing.
sub virtual_package_info
{
return ( );
}
# check_files(package, version)
# 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 ($name, $ver) = @_;
local $i = 0;
local $file;
local $qm = quotemeta($name.($ver ? '='.$ver : '>=0'));
&open_execute_command(PKGINFO, "$pkg_info -L $qm", 1, 1);
while($file = <PKGINFO>) {
$file =~ s/\r|\n//g;
next if ($file !~ /^\//);
local $real = &translate_filename($file);
local @st = stat($real);
$files{$i,'path'} = $file;
$files{$i,'type'} = -l $real ? 3 :
-d $real ? 1 : 0;
$files{$i,'user'} = getpwuid($st[4]);
$files{$i,'group'} = getgrgid($st[5]);
$files{$i,'mode'} = sprintf "%o", $st[2] & 07777;
$files{$i,'size'} = $st[7];
$files{$i,'link'} = readlink($real);
$i++;
}
return $i;
}
# package_files(package, version)
# Returns a list of all files in some package
sub package_files
{
local ($pkg, $v) = @_;
local $qn = quotemeta($pkg.($v ? '='.$v : '>=0'));
local @rv;
&open_execute_command(RPM, "$pkg_info -L $qn", 1, 1);
while(<RPM>) {
s/\r|\n//g;
if (/^\//) {
push(@rv, $_);
}
}
close(RPM);
return @rv;
}
# 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 (%packages, $file, $i, @pkgin);
local $n = &list_packages();
for($i=0; $i<$n; $i++) {
local $qm = quotemeta($packages{$i,'name'});
&open_execute_command(PKGINFO, "$pkg_info -L $qm", 1, 1);
while($file = <PKGINFO>) {
$file =~ s/\r|\n//g;
if ($file eq $_[0]) {
# found it
push(@pkgin, $packages{$i,'name'});
}
}
close(PKGINFO);
}
if (@pkgin) {
local $real = &translate_filename($_[0]);
local @st = stat($real);
$file{'path'} = $_[0];
$file{'type'} = -l $real ? 3 :
-d $real ? 1 : 0;
$file{'user'} = getpwuid($st[4]);
$file{'group'} = getgrgid($st[5]);
$file{'mode'} = sprintf "%o", $st[2] & 07777;
$file{'size'} = $st[7];
$file{'link'} = readlink($real);
$file{'packages'} = join(" ", @pkgin);
return 1;
}
else {
return 0;
}
}
# is_package(file)
sub is_package
{
local $real = &translate_filename($_[0]);
local $qm = quotemeta($_[0]);
if (-d $_[0]) {
# A directory .. see if it contains any tgz files
opendir(DIR, $real);
local @list = grep { /\.tgz$/ || /\.tbz$/ } readdir(DIR);
closedir(DIR);
return @list ? 1 : 0;
}
elsif ($_[0] =~ /\*|\?/) {
# a wildcard .. see what it matches
local @list = glob($real);
return @list ? 1 : 0;
}
else {
# just a normal file - see if it is a package
local $cmd;
foreach $cmd ('gunzip', 'bunzip2') {
next if (!&has_command($cmd));
local ($desc, $contents);
&open_execute_command(TAR, "$cmd -c $qm | tar tf -", 1, 1);
while(<TAR>) {
$desc++ if (/^\+DESC/);
$contents++ if (/^\+CONTENTS/);
}
close(TAR);
return 1 if ($desc && $contents);
}
return 0;
}
}
# file_packages(file)
# Returns a list of all packages in the given file, in the form
# package description
sub file_packages
{
local $real = &translate_filename($_[0]);
local $qm = quotemeta($_[0]);
if (-d $real) {
# Scan directory for packages
local ($f, @rv);
opendir(DIR, $real);
while($f = readdir(DIR)) {
if ($f =~ /\.tgz$/i || $f =~ /\.tbz$/i) {
local @pkg = &file_packages("$_[0]/$f");
push(@rv, @pkg);
}
}
closedir(DIR);
return @rv;
}
elsif ($real =~ /\*|\?/) {
# Expand glob of packages
# XXX won't work in translation
local ($f, @rv);
foreach $f (glob($real)) {
local @pkg = &file_packages($f);
push(@rv, @pkg);
}
return @rv;
}
else {
# Just one file
local $cmd;
foreach $cmd ('gunzip', 'bunzip2') {
next if (!&has_command($cmd));
local $temp = &transname();
&make_dir($temp, 0700);
local $rv = &execute_command("cd $temp && $cmd -c $qm | tar xf - +CONTENTS +COMMENT");
if ($rv) {
&unlink_file($temp);
next;
}
local ($comment, $name);
&open_readfile(COMMENT, "$temp/+COMMENT");
($comment = <COMMENT>) =~ s/\r|\n//g;
close(COMMENT);
&open_readfile(CONTENTS, "$temp/+CONTENTS");
while(<CONTENTS>) {
$name = $1 if (/^\@name\s+(\S+)/);
}
close(CONTENTS);
&unlink_file($temp);
return ( "$name $comment" );
}
return ( );
}
}
# install_options(file, package)
# Outputs HTML for choosing install options
sub install_options
{
print &ui_table_row($text{'bsd_scripts'},
&ui_radio("scripts", 0, [ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]));
print &ui_table_row($text{'bsd_force'},
&ui_yesno_radio("force", 0));
}
# install_package(file, package)
# Installs the package in the given file, with options from %in
sub install_package
{
local $in = $_[2] ? $_[2] : \%in;
local $args = ($in->{"scripts"} ? " -I" : "").
($in->{"force"} ? " -f" : "");
local $qm = quotemeta($_[0]);
local $out = &backquote_logged("$pkg_add $args $qm 2>&1");
if ($?) {
return "<pre>$out</pre>";
}
return undef;
}
# install_packages(file, [&inputs])
# Installs all the packages in the given file or glob
sub install_packages
{
local $in = $_[2] ? $_[2] : \%in;
local $args = ($in->{"scripts"} ? " -I" : "").
($in->{"force"} ? " -f" : "");
local ($file, $qm);
if (-d $_[0]) {
$file = "$_[0]/*.tgz";
}
else {
$file = $_[0];
}
$qm = quotemeta($file);
$qm =~ s/\\([*?])/$1/g if ($file =~ /[\*\?]/);
local $out = &backquote_logged("$pkg_add $args $qm 2>&1");
if ($?) {
return "<pre>$out</pre>";
}
return undef;
}
# delete_package(package, &in, version)
# Totally remove some package
sub delete_package
{
local ($name, $in, $ver) = @_;
local $qm = quotemeta($name.($ver ? '='.$ver : '>=0'));
local $out = &backquote_logged("$pkg_delete $qm 2>&1");
if ($? && $ver) {
$qm = quotemeta($name.'-'.$ver);
$out = &backquote_logged("$pkg_delete $qm 2>&1");
}
if ($?) { return "<pre>$out</pre>"; }
return undef;
}
# delete_packages(&packages, &in, &versions)
# Totally remove some list of packages
sub delete_packages
{
local ($names, $in, $vers) = @_;
local @qm;
for(my $i=0; $i<@$names; $i++) {
local $qm = quotemeta($names[$i].($vers[$i] ? '='.$vers[$i] : '>=0'));
push(@qm, $qm);
}
local $out = &backquote_logged("$pkg_delete ".join(" ", @qm)." 2>&1");
if ($?) { return "<pre>$out</pre>"; }
return undef;
}
sub package_system
{
return &text('bsd_manager', "FreeBSD");
}
sub package_help
{
return "$pkg_add $pkg_info $pkg_delete";
}
1;
+1
View File
@@ -0,0 +1 @@
<header> قبول اتفاقيات الترخيص الجديدة؟ </header> حدد نعم لقبول اتفاقية الترخيص وتثبيت البرنامج. حدد لا لرفض اتفاقية الترخيص وإلغاء التثبيت. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ПРИЕМАТЕ ли нови лицензионни споразумения? </header> Изберете Да, за да приемете лицензионното споразумение и да инсталирате софтуера. Изберете Не, за да отхвърлите лицензионното споразумение и да анулирате инсталацията. <hr>
+7
View File
@@ -0,0 +1,7 @@
<header>ACCEPTA els nous acords de llicència</header>
Selecciona Sí per acceptar l'acord de llicència i instal·lar el programari.
Selecciona No per rebutjar l'acord de llicència i cancel·lar la instal·lació.
<hr>
+1
View File
@@ -0,0 +1 @@
<header> AKCEPT nové licenční smlouvy? </header> Výběrem Ano přijměte licenční smlouvu a nainstalujte software. Výběrem možnosti Ne odmítnete licenční smlouvu a zrušíte instalaci. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ACCEPT nye licensaftaler? </header> Vælg Ja for at acceptere licensaftalen og installere softwaren. Vælg Nej for at afvise licensaftalen og annullere installationen. <hr>
+1
View File
@@ -0,0 +1 @@
<header>NEUE Lizenzvereinbarungen AKZEPTIEREN?</header><br><b>Ja</b> wählen, um die Lizenzvereinbarung zu akzeptieren und die Software zu installieren.<br><b>Nein</b> wählen, um die Lizenzvereinbarung abzulehnen und die Installation abzubrechen.<hr>
+1
View File
@@ -0,0 +1 @@
<header> ΑΠΟΔΕΧΕΤΕ νέες συμφωνίες αδειών; </header> Επιλέξτε Ναι για να αποδεχτείτε τη συμφωνία άδειας χρήσης και να εγκαταστήσετε το λογισμικό. Επιλέξτε Όχι για να απορρίψετε την άδεια χρήσης και να ακυρώσετε την εγκατάσταση. <hr>
+6
View File
@@ -0,0 +1,6 @@
<header>¿ ACEPTAR los nuevos acuerdos de licencia ?</header>
Seleccione Sí para aceptar los acuerdos de licencia e instalar el software.
Seleccione No para rechazar el acuerdo de licencia y cancelar la
instalación.
<hr>
+1
View File
@@ -0,0 +1 @@
<header> Onartu lizentzia hitzarmen berriak? </header> Hautatu Bai, lizentzia hitzarmena onartu eta softwarea instalatzeko. Hautatu Ez lizentzia hitzarmena baztertzeko eta instalazioa bertan behera uzteko. <hr>
+1
View File
@@ -0,0 +1 @@
<header> توافقنامه های جدید مجوز را قبول کنید؟ </header> برای قبول توافق نامه مجوز و نصب نرم افزار بله را انتخاب کنید. برای رد توافق نامه مجوز و لغو نصب گزینه No را انتخاب کنید. <hr>
+1
View File
@@ -0,0 +1 @@
<header> HYVÄKSYT uusia lisenssisopimuksia? </header> Valitse Kyllä, kun haluat hyväksyä lisenssisopimuksen ja asentaa ohjelmiston. Valitse Ei, jos haluat hylätä lisenssisopimuksen ja peruuttaa asennuksen. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ACCEPTER de nouveaux accords de licence? </header> Sélectionnez Oui pour accepter le contrat de licence et installer le logiciel. Sélectionnez Non pour refuser le contrat de licence et annuler l&#39;installation. <hr>
+1
View File
@@ -0,0 +1 @@
<header> PRIHVATITI nove licenčne ugovore? </header> Odaberite Da kako biste prihvatili licenčni ugovor i instalirali softver. Odaberite Ne da biste odbacili licenčni ugovor i otkazali instalaciju. <hr>
+6
View File
@@ -0,0 +1,6 @@
<header>ACCEPT new license agreements?</header>
Select Yes to accept the license agreement and install the software.
Select No to reject the license agreement and cancel the
installation.
<hr>
+1
View File
@@ -0,0 +1 @@
<header> ELFOGADJA az új licencszerződéseket? </header> Válassza az Igen lehetőséget a licencszerződés elfogadásához és a szoftver telepítéséhez. Válassza a Nem lehetőséget a licencszerződés elutasításához és a telepítés visszavonásához. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ACCETTARE nuovi accordi di licenza? </header> Selezionare Sì per accettare il contratto di licenza e installare il software. Selezionare No per rifiutare il contratto di licenza e annullare l&#39;installazione. <hr>
+1
View File
@@ -0,0 +1 @@
<header>新しいライセンス契約に同意しますか? </header> [はい]を選択して、使用許諾契約に同意し、ソフトウェアをインストールします。ライセンス契約を拒否してインストールをキャンセルするには、[いいえ]を選択します。 <hr>
+1
View File
@@ -0,0 +1 @@
<header> 새로운 라이센스 계약에 동의하십니까? </header> 사용권 계약에 동의하고 소프트웨어를 설치하려면 예를 선택하십시오. 라이센스 계약을 거부하고 설치를 취소하려면 아니오를 선택하십시오. <hr>
+1
View File
@@ -0,0 +1 @@
<header> MENERIMA perjanjian lesen baru? </header> Pilih Ya untuk menerima perjanjian lesen dan pasang perisian. Pilih Tidak untuk menolak perjanjian lesen dan membatalkan pemasangan. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ACCEPT nieuwe licentieovereenkomsten? </header> Selecteer Ja om de licentieovereenkomst te accepteren en de software te installeren. Selecteer Nee om de licentieovereenkomst te weigeren en de installatie te annuleren. <hr>
+1
View File
@@ -0,0 +1 @@
<header> AKSEPT nye lisensavtaler? </header> Velg Ja for å godta lisensavtalen og installere programvaren. Velg Nei for å avvise lisensavtalen og avbryte installasjonen. <hr>
+1
View File
@@ -0,0 +1 @@
<header> AKCEPTOWAĆ nowe umowy licencyjne? </header> Wybierz Tak, aby zaakceptować umowę licencyjną i zainstalować oprogramowanie. Wybierz Nie, aby odrzucić umowę licencyjną i anulować instalację. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ACEITAR novos contratos de licença? </header> Selecione Sim para aceitar o contrato de licença e instalar o software. Selecione Não para rejeitar o contrato de licença e cancelar a instalação. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ACEITAR novos contratos de licença? </header> Selecione Sim para aceitar o contrato de licença e instalar o software. Selecione Não para rejeitar o contrato de licença e cancelar a instalação. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ПРИНИМАЕТЕ новые лицензионные соглашения? </header> Выберите Да, чтобы принять лицензионное соглашение и установить программное обеспечение. Выберите Нет, чтобы отклонить лицензионное соглашение и отменить установку. <hr>
+1
View File
@@ -0,0 +1 @@
<header> AKCEPTUJTE nové licenčné zmluvy? </header> Vyberte Áno, ak chcete prijať licenčnú zmluvu a nainštalovať softvér. Výberom položky Nie odmietnete licenčnú zmluvu a zrušíte inštaláciu. <hr>
+1
View File
@@ -0,0 +1 @@
<header> Acceptera nya licensavtal? </header> Välj Ja för att acceptera licensavtalet och installera programvaran. Välj Nej för att avvisa licensavtalet och avbryta installationen. <hr>
+1
View File
@@ -0,0 +1 @@
<header> Yeni lisans anlaşmaları KABUL EDİYOR MUSUNUZ? </header> Lisans sözleşmesini kabul etmek ve yazılımı yüklemek için Evet&#39;i seçin. Lisans sözleşmesini reddetmek ve yüklemeyi iptal etmek için Hayır&#39;ı seçin. <hr>
+1
View File
@@ -0,0 +1 @@
<header> ПРИЙМАТИ нові ліцензійні угоди? </header> Виберіть Так, щоб прийняти ліцензійну угоду та встановити програмне забезпечення. Виберіть Ні, щоб відхилити ліцензійну угоду та скасувати встановлення. <hr>
+1
View File
@@ -0,0 +1 @@
<header>接受新的许可协议吗? </header>选择是,接受许可协议并安装软件。选择“否”以拒绝许可协议并取消安装。 <hr>
+1
View File
@@ -0,0 +1 @@
<header>接受新的許可協議嗎? </header>選擇是,接受許可協議並安裝軟件。選擇“否”以拒絕許可協議並取消安裝。 <hr>
+1
View File
@@ -0,0 +1 @@
<header> هل تريد تثبيت البرنامج المطلوب تلقائيًا؟ </header> يشير إلى ما إذا كنت ترغب في تثبيت البرنامج المطلوب تلقائيًا. البرنامج المطلوب هو برنامج مطلوب لكي يعمل منتج برنامج آخر. <br><br> YES يوجه النظام إلى تثبيت أي برنامج مطلوب تلقائيًا لمنتجات البرامج التي تحددها للتثبيت. بالنسبة للتحديثات المحددة ، يؤدي اختيار &quot;نعم&quot; إلى توجيه النظام لتثبيت أي تحديثات برامج حالية موجودة على وسائط التثبيت. <br><br> إذا قمت بتعيين الخيار &quot;الكتابة فوق نفس الإصدارات أو أحدث&quot; إلى &quot;نعم&quot; ، يجب عليك تعيين الخيار &quot;تثبيت برنامج REQUISITE تلقائيًا&quot; على &quot;لا&quot;. <br><br> لعرض قائمة بمنتجات البرامج والمستلزمات التي سيتم تثبيتها ، قم بتعيين الخيار &quot;معاينة التثبيت&quot; على &quot;نعم&quot;. <br><br> NO يوجه النظام إلى عدم تثبيت البرامج المطلوبة لمنتجات البرامج التي تحددها للتثبيت. إذا اخترت &quot;لا&quot; وكان النظام يواجه طلبًا مفقودًا أثناء تثبيت المنتج ، فسيتم إلغاء تثبيت هذا المنتج. يسرد النظام المطلوب المفقود ثم يواصل تثبيت البرامج الأخرى. <hr>
+1
View File
@@ -0,0 +1 @@
<header> АВТОМАТИЧНО инсталирате ли необходимия софтуер? </header> Показва дали искате автоматично да инсталирате необходимия софтуер. Requisite software е софтуер, който е необходим за функциониране на друг софтуерен продукт. <br><br> ДА инструктира системата автоматично да инсталира всеки софтуер, който е необходимо за софтуерните продукти, които сте избрали за инсталиране. За избрани актуализации, избирането на YES също така инструктира системата да инсталира всички заместващи актуализации на софтуера, намерени на инсталационния носител. <br><br> Ако зададете опцията &quot;СВЪРЗВЕТЕ същите или по-нови версии&quot; на ДА, трябва да зададете опцията &quot;Автоматично инсталиране на ИЗИСКВАНЕ на софтуера&quot; на НЕ. <br><br> За да видите списък на софтуерни продукти и реквизити, които ще бъдат инсталирани, задайте опцията „ПРЕДВИЖТЕ инсталацията“ на ДА. <br><br> НЕ инструктира системата НЕ да инсталира софтуер, който е необходимо за софтуерните продукти, които сте избрали за инсталиране. Ако изберете НЕ и системата срещне липсващ реквизит по време на инсталирането на продукт, инсталирането на този продукт се анулира. Системата изброява липсващия реквизит и след това продължава да инсталира друг софтуер. <hr>
+28
View File
@@ -0,0 +1,28 @@
<header>Instal·la AUTOMÀTICAMENT el programari necessari</header>
Indica si vols instal·lar automàticament el programari necessari.
El programari necessari és aquell programari que un altre producte
necessita per funcionar.
<br><br>
SÍ li diu al sistema que instal·li automàticament qualsevol programari
que sigui necessari per a productes de programari que vulguis instal·lar.
Per a actualitzacions seleccionades, SÍ també li diu al sistema
que instal·li qualsevol actualització corresponent que trobi al
mitjà d'instal·lació.
<br><br>
Si estableixes l'opció "REESCRIU les versions iguals o més noves" a SÍ,
has de posar l'opció Instal·la AUTOMÀTICAMENT el programari necessari a NO.
<br><br>
Per veure una llista dels productes i requisits de programari que
s'instal·laran, estableix l'opció "Només VISTA PRÈVIA" a SÍ.
<br><br>
NO li diu al sistema que NO instal·li els programari necessari per als
productes de programari que seleccionis per instal·lar. Si tries NO
i el sistema es troba a faltar programari durant la instal·lació d'un
producte, es cancel·larà la instal·lació d'aquest producte. El sistema
llista el programari necessari, i llavors continua instal·lant la resta
de productes.
<hr>

Some files were not shown because too many files have changed in this diff Show More