#!/bin/bash
#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 .
baseurl='https://www.debian.org'
# "seclines" are the lines from https://www.debian.org/security (or
# security.debian.org), which contains the "Recent Advisories"# the seclines
# are in the form: [date] [DSA-number] [package name] "security update"
# Check if wget of curl exists and is executable - then get the HTML document,
# print it to stdout and save it in Variable "seclines".
# Of course, wget and curl have to be silent/quiet.
if [[ -x /usr/bin/wget ]]; then
download_cmd () { /usr/bin/wget -qO- "$@"; }
seclines="$(download_cmd $baseurl/security/)"
[[ -z "$seclines" ]] && exit
elif [[ -x /usr/bin/curl ]]; then
download_cmd () { /usr/bin/curl -s "$@"; }
seclines="$(download_cmd $baseurl/security/)"
[[ -z "$seclines" ]] && exit
else
printf '%s\n' "Unable to find /usr/bin/wget or /usr/bin/curl. One of them is needed to download the document from $baseurl/security/"
exit
fi
# a list of all packages currently installed with their version
installeddebs="$(dpkg-query -W -f='${binary:Package} ${Version}\n')"
# a list of all packages currently installed with their source package
dpkgsrclist="$(dpkg-query -W -f='${source:Package} ${binary:Package}\n')"
get_srcpackage () {
cut -d' ' -f5 <<< "$line"
}
# generate the DSA-URLs by grabbing the DSA-XXXX from the security information
# lines and ...
urlline_tmp () {
sed -n 's/.*\(DSA-[^ ]*\).*/\1/;s/DSA/dsa/p' <<< "$line"
}
# ... appending it to https://www.debian.org/security/
urllines_cmd () {
urlline_raw="$baseurl/security/$(date '+%Y')/$(urlline_tmp)"
urlline="$(printf '%b\n' "\033[01;34m $urlline_raw\033[00m")"
}
# check if binarie packages (= debnames) from the sourcepackage are installed
check_source () {
unset error
if ! grep -q "^$srcpackage\ " <<< "$dpkgsrclist"; then
error=y
fi
}
# get a list of the installed debnames of the sourcepackage
parse_source () {
sed -n "/^$srcpackage\ / {s/[^ ]*\ //p}"
}
# get new version of the source package
parse_urlline () {
grep -o '[^ ]*deb9u[0-9]*'
}
# get the version for each debname
extract_version () {
sed -n "/^$debname\ / {s/[^ ]*\ //p}" <<< "$installeddebs"
}
# get the versions of the installed binary packages (debnames) of a source package
checkupdate_cmd () {
unset installedversions
# the name of the source package, for example "firefox-esr"
# the names of the deblist that are built from this source package, for
# example "firefox-esr-dev" or "firefox-esr"
check_source
if [[ $error != y ]]; then
deblist="$(parse_source <<< "$dpkgsrclist")"
# the new version of the packages from this source package
newversion_tmp=$(download_cmd "$urlline_raw" | parse_urlline)
[[ -z $newversion_tmp ]] && stable=n
newversion=${newversion_tmp/*:/}
while read debname; do
version_tmp=$(extract_version)
installedversions+=(${version_tmp/*:/})
done <<< "$deblist"
fi
}
search_cmd () {
printf '%s\n' "${installedversions[@]}" | grep "$1" "$2"
}
sed_color () {
sed_color_var=$(printf '%b\n' "\033[01;3$1m$srcpackage \033[00msecurity update \033[00;3$1m$2\033[00m")
sed "s/$srcpackage security update/$sed_color_var/" <<< "$line"
}
colorise_cmd () {
if [[ $stable == n ]]; then
sed_color 2 "No update for stable distribution."
elif [[ -z "${installedversions[@]}" ]]; then
if [[ $error == y ]]; then
sed_color 3 "No debs of this package installed."
else
sed "s/$/$(printf '%b\n' " \033[01;31mAn error occured.\033[00m")/" <<< "$line"
fi
elif search_cmd -q "bpo"; then
if search_cmd -qv "bpo"; then
installedversions=($(printf '%s\n' "${installedversions[@]}" | sed "s/.*bpo.*//;/^$/d"))
if search_cmd -qx "$newversion"; then
if search_cmd -qxv "$newversion"; then
sed_color 1 "There are backports and partial upgraded packages."
else
sed_color 2 "There are backports and upgraded packages."
fi
else
sed_color 1 "There are backports and not upgraded packages."
fi
else
sed_color 2 "There are only backports of this package packages."
fi
elif search_cmd -qx "$newversion"; then
if search_cmd -qxv "$newversion"; then
sed_color 1 "(partial upgraded)"
else
sed "s/$srcpackage/$(printf '%b\n' "\033[01;32m$srcpackage\033[00m")/" <<< "$line"
fi
else
sed "s/$srcpackage/$(printf '%b\n' "\033[01;31m$srcpackage\033[00m")/" <<< "$line"
fi
}
old_update () {
sed_color 1 "Update deprecated."
}
parse_seclines () {
sed -n '/security\ update
$/ {s/<[^>]*>//gp}' <<< "$seclines"
}
output="$(parse_seclines | while read line; do
srcpackage="$(get_srcpackage)"
export srcpackage
if ! grep -qx "$srcpackage" <<< "$(printf '%s\n' "${database[@]}")"; then
urllines_cmd && checkupdate_cmd
colorise_cmd && printf '%s\n\n' "$urlline"
else
urllines_cmd && old_update
printf '%s\n\n' "$urlline"
fi
database+=($srcpackage)
unset stable
done)"
# Check for pager less, than for pager more. If both are unavailable, print to stdout.
if [[ -x /usr/bin/less ]]; then
less -R <<< "$output"
elif [[ -x /bin/more ]]; then
more <<< "$output"
else
printf '%s\n' "$output"
fi