#!/usr/bin/perl ############################################################################### # # # IPFire.org - A linux based firewall # # Copyright (C) 2007-2021 IPFire Team # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # # # ############################################################################### ### Clean up our environment # delete @ENV{qw(IFS CDPATH ENV BASH_ENV PATH)}; $< = $>; # Store keys here $ENV{"GNUPGHOME"} = "/opt/pakfire/etc/.gnupg"; require "/opt/pakfire/lib/functions.pl"; my $interactive = 1; my $force = "noforce"; my $locked; &Pakfire::logger("PAKFIRE INFO: IPFire Pakfire $Conf::version started!"); ### Check if we are running as root # my $user = qx(whoami); chomp($user); unless ( "$user" eq "root" ) { &Pakfire::message("PAKFIRE ERROR: You must run pakfire as user root!"); exit 1; } unless ( -e "/var/ipfire/red/active" ) { &Pakfire::message("PAKFIRE ERROR: You need to be online to run pakfire!"); exit 2; } # Check if a lockfile already exists. if (-e "$Pakfire::lockfile") { &Pakfire::message("PAKFIRE ERROR: Another instance of pakfire is already running!"); exit 1; } # Write lockfile. open(LOCK, ">$Pakfire::lockfile"); # Pakfire has locked in this session set locket to "1". $locked = "1"; # Close filehandle. close(LOCK); ### Check if we are started by another name # if ( $0 =~ /pakfire-update$/ ) { &Pakfire::message("CRON INFO: Running an update"); my $random = int(rand(60)); &Pakfire::logger("CRON INFO: Waiting for $random seconds."); sleep($random); $ARGV[0] = "update"; $interactive = 0; } elsif ( $0 =~ /pakfire-upgrade$/ ) { &Pakfire::message("CRON INFO: Running an upgrade"); my $random = int(rand(3600)); &Pakfire::logger("CRON INFO: Waiting for $random seconds."); sleep($random); $ARGV[0] = "upgrade"; $interactive = 0; } unless (@ARGV) { &Pakfire::usage; } foreach (@ARGV) { if ("$_" =~ "^-") { # Turn off interactive mode $interactive = 0 if ("$_" eq "--non-interactive"); $interactive = 0 if ("$_" eq "-y"); # Turn off shell colors - Bad for displaying in webinterface $Pakfire::enable_colors = 0 if ("$_" eq "--no-colors"); # Turn on force mode $force = "force" if ("$_" eq "-f" ); $force = "force" if ("$_" eq "--force" ); } } if ("$ARGV[0]" eq "install") { shift; ### Make sure that the list is not outdated. &Pakfire::dbgetlist("noforce"); my %paklist = &Pakfire::dblist("all"); my $dep; my @deps; my $pak; my @paks; my @temp; my $return; my @all; foreach $pak (@ARGV) { unless ("$pak" =~ "^-") { if (defined $paklist{$pak}) { if ("$paklist{$pak}{'Installed'}" eq "yes") { &Pakfire::message("PAKFIRE INFO: $pak is already installed"); next; } push(@paks,$pak); push(@all,$pak); @temp = &Pakfire::resolvedeps("$pak"); foreach $dep (@temp) { push(@deps,$dep) if $dep; push(@all,$dep) if $dep; } } else { &Pakfire::message(""); &Pakfire::message("PAKFIRE WARN: The pak \"$pak\" is not known. Please try running \"pakfire update\"."); } } } unless (@paks) { &Pakfire::message("PAKFIRE ERROR: No packages to install. Exiting..."); exit 1; } if (@deps) { my %sort = map{ $_, 1 } @deps; @deps = keys %sort; &Pakfire::message(""); &Pakfire::message("PAKFIRE INFO: Packages to install for dependencies:"); } foreach $dep (@deps) { my $size = &Pakfire::getsize("$dep"); $size = &Pakfire::beautifysize($size); &Pakfire::message("PAKFIRE INFO: $dep \t - $size"); } &Pakfire::message(""); &Pakfire::message(""); &Pakfire::message("PAKFIRE INFO: Packages to install:"); foreach $pak (@paks) { my $size = &Pakfire::getsize("$pak"); $size = &Pakfire::beautifysize($size); &Pakfire::message("PAKFIRE INFO: $pak \t - $size"); } my $totalsize; foreach $pak (@all) { $totalsize = ($totalsize + &Pakfire::getsize("$pak")); } $totalsize = &Pakfire::beautifysize($totalsize); &Pakfire::message(""); &Pakfire::message("PAKFIRE INFO: Total size: \t ~ $totalsize"); &Pakfire::message(""); if ($interactive) { &Pakfire::message("PAKFIRE INFO: Is this okay? [y/N]"); my $ret = ; chomp($ret); &Pakfire::logger("PAKFIRE INFO: Answer: $ret"); if ( $ret ne "y" ) { &Pakfire::message("PAKFIRE ERROR: Installation aborted."); exit 1; } } else { &Pakfire::logger("PAKFIRE INFO: Interaction skipped."); } # my %sort = map{ $_, 1 } @all; # @all = sort keys %sort; ### Download first foreach $pak (@all) { &Pakfire::getpak("$pak", ""); } &Pakfire::message(""); foreach $pak (@deps) { &Pakfire::setuppak("$pak") if ($pak ne ""); } foreach $pak (@paks) { &Pakfire::setuppak("$pak") if ($pak ne ""); } } elsif ("$ARGV[0]" eq "remove") { shift; my @paks; my $pak; foreach $pak (@ARGV) { unless ("$pak" =~ "^-") { $return = &Pakfire::isinstalled($pak); if ($return ne 0) { &Pakfire::message("PAKFIRE WARN: $pak is not installed"); next; } push(@paks, $pak); } } unless (@paks) { &Pakfire::message("PAKFIRE ERROR: No packages to remove. Exiting..."); exit 1; } &Pakfire::message(""); &Pakfire::message(""); &Pakfire::message("PAKFIRE INFO: Packages to remove:"); foreach $pak (sort @paks) { my $size = &Pakfire::getsize("$pak"); $size = &Pakfire::beautifysize($size); &Pakfire::message("PAKFIRE INFO: $pak \t - $size"); } if ($interactive) { &Pakfire::message("PAKFIRE INFO: Is this okay? [y/N]"); my $ret = ; chomp($ret); &Pakfire::logger("PAKFIRE INFO: Answer: $ret"); if ( $ret ne "y" ) { &Pakfire::message("PAKFIRE ERROR: Installation aborted."); exit 1; } } foreach $pak (@paks) { &Pakfire::removepak("$pak"); } } elsif ("$ARGV[0]" eq "update") { &Pakfire::makeuuid(); &Pakfire::getmirrors("$force"); &Pakfire::dbgetlist("$force"); &Pakfire::getcoredb("$force"); } elsif ("$ARGV[0]" eq "upgrade") { my $use_color = ""; my $reset_color = ""; if ("$Pakfire::enable_colors" eq "1") { $reset_color = "$Pakfire::color{'normal'}"; $use_color = "$Pakfire::color{'lightpurple'}"; } &Pakfire::message("CORE INFO: Checking for Core-Updates..."); ### Make sure that the core db is not outdated. &Pakfire::getcoredb("noforce"); my %coredb = &Pakfire::coredbinfo(); if (defined $coredb{'AvailableRelease'}) { &Pakfire::upgradecore(); } else { &Pakfire::message("CORE INFO: No new Core-Updates available. You are on release ".$coredb{'Release'}); } &Pakfire::message("PAKFIRE INFO: Checking for package updates..."); ### Make sure that the package list is not outdated. &Pakfire::dbgetlist("noforce"); my @deps = (); if (my %upgradepaks = &Pakfire::dblist("upgrade")) { # Resolve the dependencies of the to be upgraded packages @deps = &Pakfire::resolvedeps_recursive(keys %upgradepaks); foreach $pak (sort keys %upgradepaks) { print "${use_color}Update: $pak\nVersion: $upgradepaks{$pak}{'ProgVersion'} -> $upgradepaks{$pak}{'AvailableProgVersion'}\n"; print "Release: $upgradepaks{$pak}{'Release'} -> $upgradepaks{$pak}{'AvailableRelease'}${reset_color}\n"; } &Pakfire::message(""); &Pakfire::message("PAKFIRE UPGR: We are going to install all packages listed above."); if ($interactive) { &Pakfire::message("PAKFIRE INFO: Is this okay? [y/N]"); my $ret = ; chomp($ret); &Pakfire::logger("PAKFIRE INFO: Answer: $ret"); if ( $ret ne "y" ) { &Pakfire::message("PAKFIRE ERROR: Installation aborted."); exit 1; } } # Download packages foreach $pak (sort keys %upgradepaks) { &Pakfire::getpak("$pak", ""); } # Download dependencies foreach $pak (@deps) { &Pakfire::getpak("$pak", ""); } # Install dependencies first foreach $pak (@deps) { &Pakfire::setuppak("$pak"); } # Install all upgrades foreach $pak (sort keys %upgradepaks) { &Pakfire::upgradepak("$pak"); } } else { &Pakfire::message("PAKFIRE WARN: No new package upgrades available."); } } elsif ("$ARGV[0]" eq "list") { my $count; my $coreupdate = 0; my $use_color = ""; my $reset_color = ""; my $filter = "all"; shift if ("$ARGV[1]" =~ "^-"); if ("$ARGV[1]" =~ /installed|notinstalled|upgrade/) { $filter = "$ARGV[1]"; } elsif ($ARGV[1]) { &Pakfire::message("PAKFIRE ERROR: Not a known option $ARGV[1]"); exit 1; } my $pak; my %paklist = &Pakfire::dblist($filter); if ("$Pakfire::enable_colors" eq "1") { $reset_color = "$Pakfire::color{'normal'}"; $use_color = "$Pakfire::color{'lightgreen'}"; } # Check for available core upgrade first if list of upgrades is requested if ("$filter" eq "upgrade") { my %coredb = &Pakfire::coredbinfo(); if (defined $coredb{'AvailableRelease'}) { print "${use_color}Core-Update $coredb{'CoreVersion'}\n"; print "Release: $coredb{'Release'} -> $coredb{'AvailableRelease'}${reset_color}\n\n"; $coreupdate = 1; } } foreach $pak (sort keys %paklist) { if ("$Pakfire::enable_colors" eq "1") { if ("$paklist{$pak}{'Installed'}" eq "yes") { if (defined $paklist{$pak}{'AvailableProgVersion'}) { $use_color = "$Pakfire::color{'lightgreen'}"; } else { $use_color = "$Pakfire::color{'green'}"; } } else { $use_color = "$Pakfire::color{'red'}"; } } print "${use_color}Name: $pak\nProgVersion: $paklist{$pak}{'ProgVersion'}\n"; print "Release: $paklist{$pak}{'Release'}\nInstalled: $paklist{$pak}{'Installed'}\n"; if (defined $paklist{$pak}{'AvailableProgVersion'}) { print "Update available:\n Version: $paklist{$pak}{'ProgVersion'} -> $paklist{$pak}{'AvailableProgVersion'}\n Release: $paklist{$pak}{'Release'} -> $paklist{$pak}{'AvailableRelease'}\n"; } print "${reset_color}\n"; } $count = keys %paklist; if ($count > 0) { print "$count packages total.\n"; } else { if (! $coreupdate) { &Pakfire::message("PAKFIRE WARN: No packages where found using filter $filter."); exit 1; } } } elsif ("$ARGV[0]" eq "info") { shift; my @paks; my $pak; foreach $pak (@ARGV) { unless ("$pak" =~ "^-") { push(@paks,$pak); } } unless ("@paks") { Pakfire::message("PAKFIRE ERROR: missing package name"); Pakfire::usage; exit 1; } foreach $pak (@paks) { my %metadata = Pakfire::getmetadata($pak, "latest"); ### Check if pakfile was actually found if ($metadata{'Installed'} eq "no" && $metadata{'Available'} eq "no") { Pakfire::message("PAKFIRE WARN: Pak '$pak' not found."); last; } unless (defined $metadata{'Available'}) { Pakfire::message("PAKFIRE WARN: Unable to retrieve latest metadata for $pak. Information may be outdated.") } ### Printout metadata in a user friendly format print "Name: $metadata{'Name'}\n"; print "Summary: $metadata{'Summary'}\n"; if ($metadata{'Available'} eq "yes") { print "Version: $metadata{'AvailableProgVersion'}-$metadata{'AvailableRelease'}\n"; } else { print "Version: $metadata{'ProgVersion'}-$metadata{'Release'}\n"; } print "Size: " . Pakfire::beautifysize("$metadata{'Size'}") . "\n"; print "Dependencies: $metadata{'Dependencies'}\n"; print "Pakfile: $metadata{'File'}\n"; print "Service InitScripts: $metadata{'Services'}\n"; print "Installed: $metadata{'Installed'}\n"; ### Generate a pak status message if (! defined $metadata{'Available'}) { print "Status: unknown (an error occured retrieving latest pak metadata)"; } elsif ($metadata{'Available'} eq "no") { print "Status: obsolete (version $metadata{'ProgVersion'}-$metadata{'Release'} is installed)\n"; } elsif ($metadata{'Installed'} eq "yes" && "$metadata{'Release'}" < "$metadata{'AvailableRelease'}") { print "Status: outdated (version $metadata{'ProgVersion'}-$metadata{'Release'} is installed)\n"; } elsif ($metadata{'Installed'} eq "yes") { print "Status: up-to-date\n"; } else { print "Status: not installed\n"; } print "\n"; } } elsif ("$ARGV[0]" eq "resolvedeps") { foreach (@ARGV) { next if ("$_" eq "resolvedeps"); next if ("$_" =~ "^-"); &Pakfire::resolvedeps("$_"); } } elsif ("$ARGV[0]" eq "enable") { if ("$ARGV[1]" eq "updates") { system("ln -s ../../opt/pakfire/pakfire /etc/fcron.daily/pakfire-update"); } elsif ("$ARGV[1]" eq "upgrades") { system("ln -s ../../opt/pakfire/pakfire /etc/fcron.daily/pakfire-upgrade"); } } elsif ("$ARGV[0]" eq "disable") { if ("$ARGV[1]" eq "updates") { system("rm -f /etc/fcron.daily/pakfire-update"); } elsif ("$ARGV[1]" eq "upgrades") { system("rm -f /etc/fcron.daily/pakfire-upgrade"); } } elsif ("$ARGV[0]" eq "status") { my $exitcode = 0; my %status = &Pakfire::status; print "Core-Version: $status{'CoreVersion'}\n"; print "Core-Update-Level: $status{'Release'}\n"; print "Last update: $status{'LastUpdate'} ago\n"; print "Last core-list update: $status{'LastCoreListUpdate'} ago\n"; print "Last server-list update: $status{'LastServerListUpdate'} ago\n"; print "Last packages-list update: $status{'LastPakListUpdate'} ago\n"; print "Core-Update available: $status{'CoreUpdateAvailable'}"; print " ($status{'AvailableRelease'})" if ("$status{'CoreUpdateAvailable'}" eq "yes"); print "\nPackage-Updates available: $status{'PakUpdatesAvailable'}\n"; print "Reboot required: $status{'RebootRequired'}\n"; $exitcode += 2 if ($status{'CoreUpdateAvailable'} eq "yes"); $exitcode += 3 if ($status{'PakUpdatesAvailable'} eq "yes"); $exitcode += 4 if ($status{'RebootRequired'} eq "yes"); exit $exitcode; } else { &Pakfire::usage; } END { &Pakfire::logger("PAKFIRE INFO: Pakfire has finished. Closing."); # Check if pakfire has been locked in this session. if ($locked) { # Remove lockfile. unlink($Pakfire::lockfile); } } exit 0;