✨ add some content
This commit is contained in:
parent
30cd30bbdf
commit
ac1803fc00
6 changed files with 371 additions and 5 deletions
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"timonwong.shellcheck"
|
||||
]
|
||||
}
|
||||
25
LICENSE
25
LICENSE
|
|
@ -1,9 +1,24 @@
|
|||
MIT License
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Copyright (c) 2025 jmm
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
|
|
|
|||
252
bin/citrix-update
Executable file
252
bin/citrix-update
Executable file
|
|
@ -0,0 +1,252 @@
|
|||
#!/bin/bash
|
||||
|
||||
# name: citrix-update
|
||||
# summary: Startup script: Downloads and installs "Citrix Workspace"
|
||||
# params: none
|
||||
|
||||
########
|
||||
# INIT #
|
||||
########
|
||||
# find all download links on update page
|
||||
# find corresponding checksums
|
||||
|
||||
has_command() { # $command
|
||||
command -v "$1" &>/dev/null
|
||||
}
|
||||
|
||||
needs_commands() { # $cmd1 $cmd2 ...
|
||||
local cmd
|
||||
for cmd in "${@}"; do
|
||||
if ! has_command "${cmd}"; then
|
||||
echo "Command '${cmd}' not available!" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
needs_commands "xidel"
|
||||
|
||||
echo -n "Downloading citrix update page ... " >&2
|
||||
html_data="$(curl -sSfL 'https://www.citrix.com/downloads/workspace-app/linux/workspace-app-for-linux-latest.html')"
|
||||
echo "OK!" >&2
|
||||
|
||||
# # XPath playground
|
||||
# echo "${html_data}" | xidel - \
|
||||
# --silent \
|
||||
# --printed-node-format text \
|
||||
# --extract "links:=//div[contains(@class, 'ctx-dl-content')]//a[contains(@class, 'ctx-dl-link') and @rel]/@rel" \
|
||||
# --extract "csums:=//div[contains(@class, 'ctx-dl-content')]//ul[contains(@class, 'ctx-checksum-list')]/li[1]/text()"
|
||||
# exit 0
|
||||
|
||||
# parse using XPath
|
||||
declare -a links csums
|
||||
eval "$( \
|
||||
echo "${html_data}" | xidel - \
|
||||
--silent \
|
||||
--output-format bash \
|
||||
--extract "links:=//div[contains(@class, 'ctx-dl-content')]//a[contains(@class, 'ctx-dl-link') and @rel]/@rel" \
|
||||
--extract "csums:=//div[contains(@class, 'ctx-dl-content')]//ul[contains(@class, 'ctx-checksum-list')]/li[1]/text()" \
|
||||
)"
|
||||
|
||||
# ensure every link has a checksum
|
||||
if [[ "${!links[*]}" != "${!csums[*]}" ]]; then
|
||||
echo "Links and Checksums don't match up!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# postprocess data
|
||||
declare -A citrix_data
|
||||
for key in "${!links[@]}"; do
|
||||
link="${links["${key}"]}"
|
||||
|
||||
# if link starts with "//" (no protocol), assume https
|
||||
if [[ "${link}" == "//"* ]]; then
|
||||
link="https:${link}"
|
||||
fi
|
||||
|
||||
# extract checksum only (64 hex digits)
|
||||
csum="$( echo "${csums["${key}"]}" | grep -Eo "\<[[:xdigit:]]{64}\>" )"
|
||||
|
||||
citrix_data["${csum}"]="${link}"
|
||||
done
|
||||
|
||||
# remove intermediate containers
|
||||
unset links csums
|
||||
|
||||
#########
|
||||
# FUNCS #
|
||||
#########
|
||||
|
||||
find_link() { # $filename_regex
|
||||
local link_regex="://downloads\.citrix\.com/[[:digit:]]+/${1}\?__gda__=exp=[[:digit:]]+~acl=[^~]+~hmac=[[:digit:]a-f]{64}$"
|
||||
|
||||
for key in "${!citrix_data[@]}"; do
|
||||
if echo "${citrix_data["${key}"]}" | grep -E "${link_regex}" &>/dev/null; then
|
||||
echo "${key} ${citrix_data["${key}"]}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
find_link_deb() { # $name $arch
|
||||
case "${2}" in
|
||||
x86_64) local arch="amd64" ;;
|
||||
arm64) local arch="arm64" ;;
|
||||
*) local arch="${2}" ;;
|
||||
esac
|
||||
|
||||
find_link "${1}_[[:digit:]\.]+_${arch}\.deb"
|
||||
}
|
||||
|
||||
find_link_rpm() { # $name $flavor $arch
|
||||
find_link "${1}(:?-${2})?-[[:digit:]\.]+(:?-[[:digit:]]+)?.${3}\.rpm"
|
||||
}
|
||||
|
||||
find_link_targz() { # $arch
|
||||
case "${1}" in
|
||||
x86_64) local arch="x64" ;;
|
||||
arm64) local arch="arm64" ;;
|
||||
*) local arch="${1}" ;;
|
||||
esac
|
||||
|
||||
find_link "linux${arch}-[[:digit:]\.]+\.tar.gz"
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2155
|
||||
list_all() {
|
||||
local debs="$(find_link_deb "[[:lower:]]+" "[[:alnum:]]+")"
|
||||
local debc="$(echo "${debs}" | wc -l)"
|
||||
echo "deb:"
|
||||
echo "${debs}"
|
||||
|
||||
local rpms="$(find_link_rpm "[[:alpha:]]+" "[[:lower:]]+" "[[:alnum:]_]+")"
|
||||
local rpmc="$(echo "${rpms}" | wc -l)"
|
||||
echo "rpm:"
|
||||
echo "${rpms}"
|
||||
|
||||
local tars="$(find_link_targz "[[:alnum:]]+")"
|
||||
local tarc="$(echo "${tars}" | wc -l)"
|
||||
echo "tar.gz:"
|
||||
echo "${tars}"
|
||||
|
||||
local anys="$(find_link "[[:alnum:]\._-]+")"
|
||||
local anyc="$(echo "${anys}" | wc -l)"
|
||||
echo "any:"
|
||||
echo "${anys}"
|
||||
|
||||
if [ $(( debc + rpmc + tarc )) -ne $(( anyc )) ]; then
|
||||
echo "Not all links matched!" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
download_gui() { # $link $csum $destfile
|
||||
needs_commands "curl" "zenity" "sha256sum" || return 1
|
||||
echo "Downloading '${1}' to '${3}'"
|
||||
|
||||
curl -fL -o "${3}" "${1}" &
|
||||
local curlpid=$!
|
||||
|
||||
yes | zenity \
|
||||
--progress --pulsate --auto-close \
|
||||
--title="Downloading" \
|
||||
--text="Downloading '${3}' ..." &
|
||||
local zenpid=$!
|
||||
|
||||
while kill -0 "${curlpid}" 2>/dev/null; do
|
||||
if ! kill -0 "${zenpid}" 2>/dev/null; then
|
||||
# progress bar died; ask for abort
|
||||
if zenity \
|
||||
--question \
|
||||
--text="Abort Download?"; then
|
||||
kill "${curlpid}" 2>/dev/null || true
|
||||
echo "Download cancelled!" >&2
|
||||
break
|
||||
fi
|
||||
|
||||
# restart progress bar
|
||||
yes | zenity \
|
||||
--progress --pulsate --auto-close \
|
||||
--title="Downloading" \
|
||||
--text="Downloading '${3}' ..." &
|
||||
zenpid=$!
|
||||
fi
|
||||
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
kill "${zenpid}" 2>/dev/null || true
|
||||
wait "${curlpid}"
|
||||
|
||||
if [ "$( sha256sum "${3}" | cut -d' ' -f1 )" = "${2}" ]; then
|
||||
echo "SHA256 ${2} OK!" >&2
|
||||
return 0
|
||||
else
|
||||
echo "SHA256 ${2} mismatch!" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_deb() { # $name
|
||||
needs_commands "dpkg-query" "gdebi-gtk" || return 1
|
||||
|
||||
local arch
|
||||
arch="$(uname -m)"
|
||||
echo "Trying to install ${1} DEB for ${arch}" >&2
|
||||
|
||||
local link
|
||||
if ! link="$(find_link_deb "${1}" "${arch}")"; then
|
||||
echo "No DEB found!" >&2
|
||||
return 1
|
||||
elif [ "$(echo "${link}" | wc -l)" -ne 1 ]; then
|
||||
echo "More than one DEB found!" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local csum
|
||||
csum="$( echo "${link}" | cut -d' ' -f1 )"
|
||||
link="$( echo "${link}" | cut -d' ' -f2 )"
|
||||
|
||||
local version_available
|
||||
version_available="$(echo "${link}" | sed -r 's/^.*\/[^_]+_([[:digit:]\.]+)_[^\.]+\.deb.*$/\1/')"
|
||||
|
||||
local version_installed
|
||||
if version_installed="$(dpkg-query --show --showformat='${Version}\n' ${1} &> /dev/null)" \
|
||||
&& [ "${version_available}" = "${version_installed}" ]; then
|
||||
echo "Newest version already installed!" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! zenity \
|
||||
--question \
|
||||
--title="New Version Available" \
|
||||
--text="<span size=\"xx-large\">Citrix Upgrade Available!</span>\n\nInstall ${1} version <b>${version_available}</b> now?"; then
|
||||
echo "Installation of ${1} cancelled!" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local destfile
|
||||
destfile="$(mktemp --tmpdir "XXXXX_${1}_${version_available}.deb")"
|
||||
|
||||
if download_gui "${link}" "${csum}" "${destfile}"; then
|
||||
echo "Download for ${1} successful!" >&2
|
||||
gdebi-gtk "${destfile}"
|
||||
fi
|
||||
|
||||
rm -f "${destfile}"
|
||||
echo "Cleaned up '${destfile}'" >&2
|
||||
return 0
|
||||
}
|
||||
|
||||
########
|
||||
# MAIN #
|
||||
########
|
||||
|
||||
list_all > /dev/null
|
||||
|
||||
if has_command "apt"; then
|
||||
install_deb "icaclient" || exit 1
|
||||
install_deb "ctxusb" || exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
66
bin/system-update
Executable file
66
bin/system-update
Executable file
|
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh
|
||||
|
||||
# name: system-update
|
||||
# summary: - runs all relevant update commands for a machine
|
||||
# - automatically detects and handles apt, snap and flatpak
|
||||
# - fully POSIX shell compliant
|
||||
# params: none
|
||||
|
||||
# check if a command is available
|
||||
has_command() { # $command
|
||||
command -v "$1" 1>/dev/null 2>/dev/null
|
||||
}
|
||||
|
||||
# run self as root
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
if has_command sudo; then
|
||||
# shellcheck disable=SC2068
|
||||
exec sudo "$(readlink -f "$0")" $@
|
||||
else
|
||||
echo "This script is designed to be run as root!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# handle apt packages
|
||||
if has_command apt-get; then
|
||||
set -ex
|
||||
# update package sources
|
||||
apt-get --yes update
|
||||
# upgrade installed packages
|
||||
apt-get --yes dist-upgrade
|
||||
# remove unused dependencies
|
||||
apt-get --yes --purge autoremove
|
||||
# remove leftover local archives
|
||||
apt-get --yes autoclean
|
||||
# remove leftover config files
|
||||
apt-get --yes purge '?config-files'
|
||||
set +ex
|
||||
fi
|
||||
|
||||
# handle snaps
|
||||
if has_command snap; then
|
||||
set -ex
|
||||
# upgrade installed snaps
|
||||
snap refresh
|
||||
# remove disabled snaps: https://askubuntu.com/a/1040131
|
||||
set +x
|
||||
env LANG=en_US.UTF-8 snap list --all \
|
||||
| awk '/disabled/{print $1, $3}' \
|
||||
| while read -r snap_name snap_revision; do
|
||||
set -x
|
||||
snap remove "${snap_name}" --revision="${snap_revision}"
|
||||
set +x
|
||||
done
|
||||
set +ex
|
||||
fi
|
||||
|
||||
# handle flatpaks
|
||||
if has_command flatpak; then
|
||||
set -ex
|
||||
# upgrade installed flatpaks
|
||||
flatpak update --noninteractive
|
||||
# remove unused flatpaks
|
||||
flatpak uninstall --noninteractive --unused
|
||||
set +ex
|
||||
fi
|
||||
25
conf/profile
Normal file
25
conf/profile
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
_include_bindir_in_path() {
|
||||
if [ -d "${1}" ]; then
|
||||
real_bin_dir="$(readlink -f "${1}" )"
|
||||
export PATH="${real_bin_dir}:${PATH}"
|
||||
fi
|
||||
}
|
||||
|
||||
# include ~/bin and ~/bin.d/* in PATH
|
||||
for bin_candidate in "${HOME}/bin/" "${HOME}/bin.d/"*; do
|
||||
_include_bindir_in_path "${bin_candidate}"
|
||||
done
|
||||
|
||||
# ... also include a few well-known bin directories
|
||||
for bin_location in ".local" ".poetry" ".cargo"; do
|
||||
_include_bindir_in_path "${HOME}/${bin_location}/bin/"
|
||||
done
|
||||
|
||||
# ... include ALL OF THE ~/.whatever/bin directories (possibly unsafe)
|
||||
# for bin_candidate in "${HOME}/."*"/bin/"; do
|
||||
# _include_bindir_in_path "${bin_candidate}"
|
||||
# done
|
||||
|
||||
unset -f _include_bindir_in_path
|
||||
3
conf/zshenv
Normal file
3
conf/zshenv
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/zsh
|
||||
|
||||
alias apt-install-url='function _apt-install-url(){ local destfile="$(mktemp --suffix ".deb")"; wget --quiet --show-progress --output-document "${destfile}" "${1}"; sudo apt install "${destfile}"; rm -f "${destfile}"; unset -f _apt-install-url; }; _apt-install-url'
|
||||
Loading…
Reference in a new issue