You are not logged in.
[ $# -gt 1 ]
Offline
Turned my old phone into webcam https://gist.github.com/ugjka/fd41efb07 … 4232786eb9
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
Edit: added -u and -b options
#!/bin/bash
gitaurfolder=$HOME/.cache/aurgits
function print_help {
underline=$(tput smul)
nounderline=$(tput rmul)
echo "
Check source version for -git packages installed from AUR. Support local installed packages or repoctl
${underline}Usage${nounderline}: ${0##*/} [OPTIONS] [repoctl]
${underline}Options${nounderline}:
-h Print help information
-u Print URL source for updates
-b Build updates. Default option for makepkg is '-rfs' or can be added, e.g. '-b rsCc'
-q Supress info, show info about updates only
-c Clean cache folder after checking
${underline}Modes${nounderline}:
* Check installed packages. Default mode
repoctl Check packages at you own repository
"
}
function cleanfolder (){
if [ -n "$clean" ]; then
[ -z "$lessinfo" ] && echo -e "\nCleaning cache..."
find "$gitaurfolder" -delete
fi
}
function checkaurgit (){
if [ "$1" == "repoctl" ]; then
mapfile -t gitpackages < <(repoctl list | grep "git")
mapfile -t gitpackageversions < <(repoctl list -v | grep "git" | cut -d " " -f2)
else
mapfile -t gitpackages < <(pacman -Qq | grep "\-git$")
mapfile -t gitpackageversions < <(pacman -Q | grep "\-git " | cut -d " " -f2)
fi
[ ! -d "$gitaurfolder" ] && mkdir "$gitaurfolder"
pushd "$gitaurfolder" > /dev/null || exit 1
for index in ${!gitpackages[*]}; do
gitpackage=${gitpackages[$index]}
gitpackageversion=${gitpackageversions[$index]}
[ -z "$lessinfo" ] && echo -e "\nChecking package: $gitpackage"
[ ! -d "$gitpackage" ] && git clone --quiet "https://aur.archlinux.org/$gitpackage.git" 2> /dev/null
builtin cd "$gitpackage" || exit 2
mapfile -t giturl < <(grep -Po '(?<=git\+)http.*' .SRCINFO | sed 's|#branch=| -b |')
[ ! -d "${gitpackage%-git}" ] && git clone --quiet "${giturl[@]}" "${gitpackage%-git}" 2> /dev/null
builtin cd "${gitpackage%-git}" || exit 3
git pull --quiet
gitversion=$(
set -euo pipefail;
git describe --long --tags --abbrev=7 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g;s/^v//' \
|| printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
)
if [[ ! "$gitpackageversion" =~ ${gitversion: -6} ]]; then
echo "$gitpackage ${gitpackageversion%-*} -> $gitversion"
[ -n "$show_url" ] && [ -z "$lessinfo" ] && grep -Po '(?<=url = ).*' ../.SRCINFO
updpackages+=("$gitpackage")
else
[ -z "$lessinfo" ] && echo "Version ${gitpackageversion%-*} is up to date"
fi
builtin cd "$gitaurfolder" || exit 2
done
popd > /dev/null || exit 1
}
while getopts ':hub:qc' option; do
case "$option" in
h ) print_help; exit 0;;
u ) show_url="y";;
b ) mkpgoptions="-$OPTARG";;
q ) lessinfo="y";;
c ) clean="y";;
: ) mkpgoptions="-rfs";;
\? ) [ -n "$OPTARG" ] && { echo "Option not found, try -h" && exit 1; }
esac
done
shift $((OPTIND - 1))
if [ "$1" == "repoctl" ] || [ "$mkpgoptions" == "-repoctl" ]; then
[ -x /usr/bin/repoctl ] && checkaurgit repoctl || echo "Repoctl not installed. Exiting..."
else
checkaurgit
fi
if [ -n "$mkpgoptions" ]; then
[ "$mkpgoptions" == "-repoctl" ] && mkpgoptions="-rfs"
for package in "${updpackages[@]}" ; do
pushd "$gitaurfolder/$package" > /dev/null || exit 1
echo -e "\nBuild $package with options $mkpgoptions"
if makepkg "$mkpgoptions" && [ -x /usr/bin/repoctl ]; then
read -n 1 -p "Add package to repository? [Y/n] " -r reply
[ "$reply" != "" ] && echo
if [ "$reply" = "${reply#[Nn]}" ]; then
find ! -name '*debug*' -name '*.pkg.tar.zst' -exec repoctl add {} \;
fi
fi
popd > /dev/null || exit 1
done
fi
cleanfolder
Last edited by Nebulosa (2024-03-14 06:48:55)
Offline
#!/bin/bash
# This script makes a BTRFS subvolume with latest Archlinux iso image and sets a new entry in GRUB menu
# which allows you to boot from iso image directly. Some kind of RescueDisk that hard to broke
# because it is not mounted in your daily work routine. Feel free to run this script once a month,
# script will update the iso image to the latest from the mirror.
# Requires: BTFRS, GRUB, curl, grep, sed, sha256sum, tee, cat, find
mirror="mirror.ams1.nl.leaseweb.net" # More mirrors can be found here: https://archlinux.org/download/
subvol="@archiso"
iso="archlinux-x86_64.iso"
folder="/mnt/archiso"
rootdrive=$(mount | grep -Po '^.*(?= on \/ type btrfs)')
[ "$rootdrive" == "" ] && echo "This script works only with BTRFS" && exit 1
[ ! -e /etc/default/grub ] && echo "This script works only with GRUB" && exit 1
function writetogrub(){
sudo sed -i 's/GRUB_TIMEOUT=0/GRUB_TIMEOUT=1/' /etc/default/grub # At least one second needed
cat << EOF > /tmp/40_custom
menuentry 'Boot from archlinux.iso' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod btrfs
insmod loopback
probe -u \$root --set=rootuuid
set imgdevpath="/dev/disk/by-uuid/\$rootuuid"
set isofile='/@archiso/archlinux-x86_64.iso'
loopback loop \$isofile
linux (loop)/arch/boot/x86_64/vmlinuz-linux img_dev=\$imgdevpath img_loop=\$isofile earlymodules=loop
initrd (loop)/arch/boot/x86_64/initramfs-linux.img
}
EOF
if [ "$(wc -l < /etc/grub.d/40_custom)" -eq 5 ]; then
cat /tmp/40_custom | sudo tee -a /etc/grub.d/40_custom > /dev/null && sudo grub-mkconfig -o /boot/grub/grub.cfg
find /tmp/40_custom -delete
fi
}
function checkiso(){
curl -s "https://$mirror/archlinux/iso/latest/sha256sums.txt" | grep $iso | sha256sum -c --
}
if [ "$(sudo btrfs subvolume list / | grep 'top level [0-9] path '$subvol)" == "" ]; then
sudo mount "$rootdrive" /mnt
pushd "/mnt" > /dev/null && sudo btrfs subvolume create $subvol && popd > /dev/null
sudo umount /mnt && writetogrub || exit 1
fi
if [ "$(sudo btrfs subvolume list / | grep 'top level [0-9] path '$subvol)" != "" ]; then
sudo mkdir -p $folder && sudo mount -o compress=zstd:3,subvol=$subvol "$rootdrive" $folder
pushd "$folder" > /dev/null || exit 2
if checkiso; then
echo "The latest Archlinux iso image already exists on the system. Nothing to do."
else
echo "Downloading $iso from $mirror to $HOME..."
builtin cd "$HOME" || exit 3
curl -L -O -C - "https://$mirror/archlinux/iso/latest/$iso"
sudo curl -o "$folder/$iso" "FILE:///home/$(whoami)/$iso"
checkiso && find "$HOME"/$iso -delete || echo "Checksum error!"
fi
builtin cd / && sudo umount $folder && sudo find $folder -delete
popd > /dev/null || exit 2
fi
Edit: fixies
Last edited by Nebulosa (2024-04-11 19:01:59)
Offline
easily check a dependency list
# check dependencies
for dependency in "sed" "git"; do
command -v $dependency >/dev/null 2>&1 || { echo "Require $dependency command. Not found." >&2; exit 1; }
done
retry some code (in the while line)
# Retry failed command two more times for a total of 3 tries
max_retries=2;
while ! ls i_do_not_exist
do
((max_retries--)) || break
echo "Retrying after delay... ${max_retries} try left"
sleep 2;
done
my favorite of late: a way to add comments to a long list of parameters. very handy with things that lack conf files when they should exist (like rclone) or when they are just long lived hacks (like dealing with docker)
# comment parameters using an array! copy literary from the command --help and add `#` after the actual flag
RCLONEFLAGS=(
--progress # show progress
--no-update-modtime # trust server time instead of file meta-data
...million more lines...
)
rclone copy ${RCLONEFLAGS[@]}
and the bane of my existence with bash. it joins quoted strings.
# x='a'"'"'b' === 'a' + "'" + 'b' === 'a'\''b' => 'a'+\'+'b' => 'a\'b'
And you cannot escape single quotes, so the last one up there is "invalid" bash.
Offline
easily check a dependency list...
I think you mean `pacman -T sed git`.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
gcb wrote:easily check a dependency list...
I think you mean `pacman -T sed git`.
That's a package search
It's fine if you are coding script hooks for a package or install inscripts. other than that it is the wrong tool.
Offline
Interactively creates a live ISO menu entry at boot with dependency checks and idempotency:
#!/bin/bash
# Auto escalate to root
if [ "$(id -u)" -ne 0 ]; then
echo "Attempting to escalate to root..."
sudo "$0" "$@"
exit $?
fi
# Variables
grub_cfg_path="/boot/grub/grub.cfg"
custom_entry_path="/etc/grub.d/40_custom"
entry_identifier="Arch" # Unique identifier for the custom entry
# Prompt for the ISO path
read -p "Enter the path to the ISO file (e.g., /boot/isos/arch.iso): " iso_path
# Check and create grub.cfg and 40_custom if they do not exist
if [ ! -f "${grub_cfg_path}" ]; then
echo "grub.cfg not found. Creating..."
touch "${grub_cfg_path}"
fi
if [ ! -f "${custom_entry_path}" ]; then
echo "40_custom not found. Creating..."
cat << 'EOF' > "${custom_entry_path}"
#!/bin/sh
exec tail -n +3 $0
EOF
chmod +x "${custom_entry_path}"
fi
# Check for existing menu entry to ensure idempotency
if ! grep -q "${entry_identifier}" "${custom_entry_path}"; then
# Append custom menu entries to 40_custom if not already present
cat << EOF >> "${custom_entry_path}"
# Custom menu entries
menuentry "${entry_identifier}" {
iso_path="${iso_path}"
export iso_path
search --set=root --file \$iso_path
probe -u \$root --set=rootuuid
export rootuuid
loopback loop \$iso_path
root=(loop)
configfile /boot/grub/loopback.cfg
loopback --delete loop
}
menuentry 'Reboot Computer' --class restart {
reboot
}
menuentry 'Shutdown Computer' --class shutdown {
halt
}
EOF
echo "Custom GRUB entries added."
else
echo "Custom GRUB entry '${entry_identifier}' already exists. No changes made."
fi
# Update GRUB configuration
echo "Updating GRUB configuration..."
grub-mkconfig -o "${grub_cfg_path}"
echo "GRUB configuration has been updated. Please reboot to see the changes."
Offline
... creates a live ISO menu entry at boot ...
Fun fact, but I posted almost the exact same script above
Last edited by Nebulosa (2024-04-11 18:57:21)
Offline
Fun fact, but I posted almost the exact same script above :smile:
Last edited by Nebulosa (Today 12:57:21)
Hey Nebulosa,
I see you, lets take it to the next level then:
#!/bin/bash
# File: liveiso_boot_entry.sh
# Author: 4ndr0666
# Date: 04-11-2024
#
# --- // LIVEISO_BOOT_ENTRY.SH // ========
# --- // COLORS:
CYAN='\033[0;36m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
# --- // TRAP:
cleanup() {
echo -e "${CYAN}Cleaning up... Please wait."
# Add any cleanup commands here
echo -e "Cleanup complete.${NC}"
exit 1 # Ensure the script exits after cleanup
}
trap cleanup SIGINT SIGTERM EXIT
# --- // ROOT:
escalate() {
if [ "$(id -u)" -ne 0 ]; then
echo -e "${CYAN}CAUTION: You are now superuser...${NC}"
exec sudo "$0" "$@"
fi
}
# --- // DEPS:
dependencies() {
local required_cmds="curl grep sed sha256sum tee cat find jq btrfs blkid findmnt grub-mkconfig wget"
for cmd in $required_cmds; do
if ! command -v $cmd &> /dev/null; then
echo -e "${CYAN}Error: Required command '$cmd' not found.${NC}"
exit 1
fi
done
}
# --- // FS:
filesystem_type() {
read -r -p "Select your filesystem type for operations (ext4 or btrfs): " filesystem_type
if [[ $filesystem_type != "ext4" && $filesystem_type != "btrfs" ]]; then
echo -e "${CYAN}Unsupported filesystem type. Exiting.${NC}"
exit 1
fi
}
# --- // VARIABLES:
setup_variables() {
subvol="@iso_subvol"
folder="/mnt/iso_subvol"
rootdrive=$(findmnt -n -o SOURCE /)
rootuuid=$(blkid -s UUID -o value "$rootdrive")
}
# --- // BOOTLOADER:
check_bootloader() {
if [ -d /boot/efi/loader/entries ]; then
echo -e "${CYAN}System is managed by systemd-boot.${NC}"
bootloader="systemd"
elif [ -d /boot/grub ]; then
echo -e "${CYAN}System uses GRUB.${NC}"
bootloader="grub"
else
echo -e "${CYAN}No supported bootloader found. Manual configuration required.${NC}"
exit 1
fi
}
# --- // DISTROLIST:
distrolist() {
echo -e "${CYAN}Fetching available distributions...${NC}"
declare -A distros=(
["Ubuntu"]="https://www.ubuntu.com/download/desktop"
["Fedora"]="https://getfedora.org/en/workstation/download/"
["Ubuntu"]="https://www.ubuntu.com/download/desktop"
["Edubuntu"]="https://edubuntu.org/download"
["Kubuntu"]="https://kubuntu.org/getkubuntu/"
["Lubuntu"]="https://lubuntu.net/downloads/"
["Xubuntu"]="https://xubuntu.org/download"
["Ubuntu Budgie"]="https://ubuntubudgie.org/downloads"
["Ubuntu Gnome"]="https://cdimage.ubuntu.com/ubuntu-gnome/releases/"
["Ubuntu Server"]="https://www.ubuntu.com/download/server"
["Ubuntu Studio"]="https://ubuntustudio.org/download/"
["Emmabuntus"]="https://sourceforge.net/projects/emmabuntus/files/latest/download"
["Linux Mint"]="https://www.linuxmint.com/download.php"
["Linux Mint Debian"]="https://www.linuxmint.com/download_lmde.php"
["CentOS Live"]="https://www.centos.org/download/"
["CentOS Minimal"]="https://www.centos.org/download/"
["Debian Live"]="https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/"
["Fedora"]="https://getfedora.org/en/workstation/download/"
["OpenSUSE"]="https://get.opensuse.org/desktop/"
["Puppy Linux"]="http://distro.ibiblio.org/puppylinux/puppy-fossa/fossapup64-9.5.iso"
["BionicPup"]="https://distro.ibiblio.org/puppylinux/puppy-bionic/"
["Tahrpup"]="https://distro.ibiblio.org/puppylinux/puppy-tahr/iso/tahrpup64-6.0.5/tahr64-6.0.5.iso"
["Fatdog64"]="https://distro.ibiblio.org/fatdog/iso/"
["Lucid Puppy Linux"]="https://distro.ibiblio.org/pub/linux/distributions/puppylinux/puppy-5.2.8/lupu-528.005.iso"
["Precise Puppy Linux"]="https://distro.ibiblio.org/quirky/precise-5.7.1/precise-5.7.1.iso"
["Slacko Puppy"]="https://distro.ibiblio.org/puppylinux/puppy-slacko-6.3.2/64/slacko64-6.3.2-uefi.iso"
["Academix"]="https://sourceforge.net/projects/academix/files/latest/download"
["AntiX"]="https://sourceforge.net/projects/antix-linux/files/latest/download"
["Archbang"]="https://sourceforge.net/projects/archbang/files/latest/download"
["Archlinux"]="http://mirrors.us.kernel.org/archlinux/iso/latest/"
["EndeavourOS"]="https://mirrors.gigenet.com/endeavouros/iso/EndeavourOS_Galileo-Neo-2024.01.25.iso"
["Garuda Hyprland"]="https://iso.builds.garudalinux.org/iso/latest/community/hyprland/latest.iso?r2=1"
["Garuda dr460nized"]="https://iso.builds.garudalinux.org/iso/latest/garuda/dr460nized/latest.iso?r2=1"
["Garuda Gnome"]="https://iso.builds.garudalinux.org/iso/latest/garuda/gnome/latest.iso?r2=1"
["Garuda Xfce"]="https://iso.builds.garudalinux.org/iso/latest/garuda/xfce/latest.iso?r2=1"
["Manjaro"]="https://download.manjaro.org/kde/23.1.4/manjaro-kde-23.1.4-240406-linux66.iso"
["Axyl"]="https://github.com/axyl-os/axylos-2-iso/releases/download/v2-beta-2024.04.11/axyl-v2-beta-2024.04.11-x86_64.iso"
["Archcraft"]="https://sourceforge.net/projects/archcraft/files/latest/download"
["CachyOS"]="https://iso.cachyos.org/240401/cachyos-kde-linux-240401.iso"
["BigLinux"]="https://iso.biglinux.com.br/biglinux_2024-04-05_k68.iso"
["Artix"]="https://artixlinux.org/download.php"
["Stormos"]="https://sourceforge.net/projects/hackman-linux/"
["Mabox"]="https://sourceforge.net/projects/mabox-linux/files/latest/download"
["Bluestar Linux"]="https://sourceforge.net/projects/bluestarlinux/files/latest/download"
["Bodhi"]="https://sourceforge.net/projects/bodhilinux/files/latest/download"
["CAELinux"]="https://sourceforge.net/projects/caelinux/files/latest/download"
["Calculate Linux Desktop"]="http://www.gtlib.gatech.edu/pub/calculate/release/20.6/"
["Cub Linux"]="https://sourceforge.net/projects/cublinux/files/latest/download"
["Deepin"]="https://sourceforge.net/projects/deepin/files/latest/download"
["Endeavour OS"]="https://endeavouros.com/latest-release/"
["Feren OS"]="https://sourceforge.net/projects/ferenoslinux/files/latest/download"
["JustBrowsing"]="https://sourceforge.net/projects/justbrowsing/files/latest/download"
["KDE Neon"]="https://neon.kde.org/download"
["KNOPPIX"]="http://ftp.knoppix.nl/os/Linux/distr/knoppix/KNOPPIX_V9.1CD-2021-01-25-EN.iso"
["KXStudio"]="https://sourceforge.net/projects/kxstudio/files/latest/download"
["LinuxFX"]="https://sourceforge.net/projects/linuxfxdevil/files/latest/download"
["Linux Kid X"]="https://sourceforge.net/projects/linuxkidx/files/latest/download"
["LXLE Desktop"]="https://sourceforge.net/projects/lxle/files/latest/download"
["OpenMandriva"]="https://sourceforge.net/projects/openmandriva/files/latest/download"
["mintyMac"]="http://sourceforge.net/projects/mintymacpremium/files/latest/download"
["MX Linux"]="https://sourceforge.net/projects/mx-linux/files/latest/download"
["Netrunner"]="https://www.netrunner.com/download/"
["OSGeo Live"]="https://sourceforge.net/projects/osgeo-live/files/latest/download"
["PCLinuxOS"]="https://www.pclinuxos.com/?page_id=10"
["Peach OSI"]="https://www.peachosi.com/content/download-patriot"
["Pear Linux"]="https://sourceforge.net/projects/pearoslinux/files/latest/download"
["Peppermint"]="https://peppermintos.com/guide/downloading/"
["Pinguy OS"]="https://sourceforge.net/projects/pinguy-os/files/latest/download"
["Porteus"]="http://porteus.org/porteus-mirrors.html"
["POP!_OS"]="https://pop.system76.com/"
["Q4OS"]="https://sourceforge.net/projects/q4os/files/latest/download"
["Raspberry Pi Desktop"]="https://www.raspberrypi.org/software/raspberry-pi-desktop/"
["Skywave Linux"]="https://sourceforge.net/projects/skywavelinux/files/latest/download"
["SLAX"]="https://www.slax.org/#purchase"
["SliTaZ"]="https://www.slitaz.org/en/get/"
["LuninuX OS"]="https://sourceforge.net/projects/luninuxos/files/latest/download"
["Solus"]="https://getsol.us/download/"
["SolydX"]="https://solydxk.com/downloads.php"
["Sparky Linux"]="https://sourceforge.net/projects/sparkylinux/files/latest/download"
["Sugar on a Stick"]="https://wiki.sugarlabs.org/go/Sugar_on_a_Stick"
["Terralinux"]="https://sourceforge.net/projects/terralinuxos/files/latest/download"
["Uberstudent"]="https://sourceforge.net/projects/uberstudent/files/latest/download"
["Ultimate Edition"]="https://sourceforge.net/projects/ultimateedition/files/latest/download"
["Xiaopan"]="https://sourceforge.net/projects/xiaopanos/files/latest/download"
["Zorin OS Core"]="https://zorinos.com/download/"
["Kodachi"]="https://sourceforge.net/projects/linuxkodachi/files/latest/download"
["Liberte"]="https://sourceforge.net/projects/liberte/files/latest/download"
["4M Linux"]="https://sourceforge.net/projects/linux4m/files/latest/download"
["Antivirus Live CD"]="https://sourceforge.net/projects/antiviruslivecd/files/latest/download"
["AVIRA AntiVir Rescue CD"]="https://download.avira.com/download/rescue-system/avira-rescue-system.iso"
["Dr.Web LiveDisk"]="https://download.geo.drweb.com/pub/drweb/livedisk/drweb-livedisk-900-cd.iso"
["ESET SysRescue Live"]="https://www.eset.com/int/support/sysrescue/#download"
["GDATA Rescue CD"]="https://secure.gd/dl-int-bootcd"
["Kaspersky Rescue Disk"]="https://rescuedisk.s.kaspersky-labs.com/updatable/2018/krd.iso"
["Acronis True Image"]="NONE"
["BackBox"]="https://www.backbox.org/download/"
["Boot Repair Disk"]="https://sourceforge.net/projects/boot-repair-cd/files/latest/download"
["Caine"]="https://www.caine-live.net/page5/page5.html"
["Clonezilla"]="https://clonezilla.org/downloads.php"
["DBAN"]="https://sourceforge.net/projects/dban/files/latest/download"
["Demon Linux"]="https://demonlinux.com/"
["DRBL"]="https://sourceforge.net/projects/drbl/files/latest/download"
["EASEUS Disk Copy"]="https://download.easeus.com/free/EaseUS_DiskCopy_Home.exe"
["Finnix"]="https://www.finnix.org/Download"
["G4L"]="https://sourceforge.net/projects/g4l/files/latest/download"
["GParted"]="https://sourceforge.net/projects/gparted/files/latest"
["GRML"]="https://grml.org/download/"
["Kali"]="https://www.kali.org/downloads/"
["Memtest86"]="https://www.memtest86.com/download.htm"
["Memtest86+"]="https://www.memtest.org/download/5.31b/memtest86+-5.31b.bin.zip"
["Matriux"]="https://sourceforge.net/projects/matriux/files/latest/download"
["Ophcrack"]="https://sourceforge.net/projects/ophcrack/files/ophcrack-livecd/3.6.0/"
["Rescatux"]="https://sourceforge.net/projects/rescatux/files/latest/download"
["Rescuezilla"]="https://rescuezilla.com/download.html"
["Redo Backup And Recovery"]="https://sourceforge.net/projects/redobackup/files/latest/download"
["Rip Linux"]="https://sourceforge.net/projects/riplinuxmeta4s/files/latest/download"
["System Rescue"]="https://sourceforge.net/projects/systemrescuecd/files/latest/download"
["Trinity Rescue Kit"]="https://trinityhome.org/trinity_rescue_kit_download/"
["Ultimate Boot CD"]="http://www.ultimatebootcd.com/download/redirect.php"
["Wifislax"]="https://www.wifislax.com/category/download/"
["Falcon 4 Boot CD"]="NONE"
["Hiren's Boot CD"]="NONE"
["Hiren's BootCD PE"]="https://www.hirensbootcd.org/download/"
["LinuxCNC"]="https://linuxcnc.org/downloads/"
)
PS3="Please select a distribution: "
select distro in "${!distros[@]}"; do
if [ -n "$distro" ]; then
echo -e "${CYAN}You have selected: $distro${NC}"
break
else
echo -e "${CYAN}Invalid selection. Please select a valid option.${NC}"
fi
done
iso_url="${distros[$distro]}"
iso_path="/iso_storage/$distro.iso"
echo -e "${CYAN}Preparing to download $distro:${NC}"
echo -e "${CYAN}Download URL: $iso_url${NC}"
echo -e "${CYAN}Storing at: $iso_path${NC}"
}
# --- // DIR_CHECK:
ensure_directory_exists() {
local storage_dir=$(dirname "$iso_path")
if [ ! -d "$storage_dir" ]; then
echo -e "${CYAN}Storage directory $storage_dir does not exist. Creating...${NC}"
mkdir -p "$storage_dir"
if [ $? -ne 0 ]; then
echo -e "${CYAN}Failed to create storage directory. Exiting.${NC}"
exit 1
fi
echo -e "${CYAN}Directory created successfully.${NC}"
fi
}
# --- // DL_ISO:
download_iso() {
if ! wget -O "$iso_path" "$iso_url"; then
echo -e "${CYAN}Download failed. Exiting.${NC}"
rm -f "$iso_path"
exit 2
fi
echo -e "${CYAN}Download complete.${NC}"
}
# --- // IDEMPOTENCY:
check_iso_existence() {
if [ -f "$iso_path" ]; then
echo -e "${CYAN}ISO for $distro already exists. Skipping download.${NC}"
else
ensure_directory_exists
download_iso
fi
}
# --- // CONFIG:
configure_bootloader() {
case $bootloader in
"grub")
echo -e "${CYAN}Adding GRUB entry for $distro...${NC}"
configure_grub
;;
"systemd")
echo -e "${CYAN}Adding systemd-boot entry for $distro...${NC}"
configure_systemd_boot
;;
esac
}
# --- // MAIN_LOGIC_LOOP:
escalate
dependencies
filesystem_type
setup_variables
check_bootloader
distrolist
check_iso_existence
configure_bootloader
if [ $? -eq 0 ]; then
echo -e "${GREEN}Operation completed successfully. Please reboot to use the new ISO boot option.${NC}"
fi
All thoughts and suggestions for further improvement are welcome!
Last edited by 4ndr0666 (2024-04-12 06:11:49)
Offline
All thoughts and suggestions for further improvement are welcome!
Hint: please check your script at https://www.shellcheck.net/ there are a lot of errors there right now.
Functions:
1. dependencies(): curl and wget for what? If I'm using ext4 why do I need install btrfs-progs? Also curl, grep, sed, sha256sum, tee, cat, find, jq, btrfs are not used in the script.
2. distrolist(): Why list of distro is so huge? Have you tested all the urls yet? Many of them is just lead to download page and don't download iso files. And if I select wrong option, it continues to run.
3. configure_bootloader(): There is no configure_grub and configure_systemd_boot in script.
Offline
#!/bin/sh
set -eu
IFS='
'
_echo() {
printf '\033[91m%s\033[0m\n' "${1}"
}
_src="${HOME}/ytdl.txt"
_wd="${HOME}/ytdl-tmp"
_dest="${HOME}/ytdl"
rm -vrf "${_wd}"
mkdir -vp "${_wd}"
mkdir -vp "${_dest}"
(
cd "${_wd}"
_echo "Running yt-dlp for: ${_src}"
yt-dlp -a "${_src}" -o "%(title)s.%(ext)s" -v --extract-audio --audio-format best
# clean up weird characters in file names
_echo "Renaming files in: ${_wd}"
perl-rename -v 's/[^a-zA-Z0-9](?![^.]*$)//g' ./*
# increase volume for Huawei Watch GT 2 Pro
for _original in ./*
do
if [ -f "${_original}" ]
then
_basename="$(basename "${_original}")"
_mp3="yt-${_basename%%.*}.mp3"
_echo "Converting ${_original} to ${_mp3}"
ffmpeg -i "${_original}" -af 'volume=3' -codec:a libmp3lame -qscale:a 4 "${_mp3}"
mv -v "${_mp3}" "${_dest}"
rm -v "${_original}"
fi
done
)
# remove working dir
rm -vrf "${_wd}"
Script that reads YouTube links from $HOME/ytdl.txt and saves audio in mp3 format to $HOME/ytdl/. Depends on yt-dlp, perl-rename, ffmpeg.
It also increases volume by a factor of 3 using ffmpeg. This is because recently I've been taking long walks and listening podcasts on my smartwatch with bluetooth headphones, and audio on that thing is waaaay to low, I guess they were afraid of hearing damage or something.
Last edited by karabaja4 (2024-04-13 23:20:10)
Offline
Since yt audio is typically not mp3 but m4a or opus, you could fetch the native audio (-f140 will get you m4a, -F for a list of codecs) and add the gain while you're converting it to mp3 locally
Offline
Since yt audio is typically not mp3 but m4a or opus, you could fetch the native audio (-f140 will get you m4a, -F for a list of codecs) and add the gain while you're converting it to mp3 locally
Updated, thanks.
I added "--audio-format best" so whatever comes out (mp4a or opus) just gets picked up by ffmpeg and mp3 encoding happens only once (with added gain).
Offline
#!/bin/bash
# LUSC - Linux UEFI STUB Creator
# 2024 by Lennart Martens - monkeynator78@gmail.com - https://github.com/lennart1978/LUSC -
# Automatically generate UEFI boot entries
# Color Codes
BLUE=$(tput setaf 4)
GREEN=$(tput setaf 2)
RED=$(tput setaf 1)
RESET=$(tput sgr0)
# Display usage information
usage() {
cat << EOF
Usage: $(basename "$0")
This is a simple interactive tool to automatically generate UEFI boot entries.
It generates efibootmgr commands and exports them to a small executable.
No changes will be written to disk before confirmation.
The EFI partition must be mountet to /boot and the kernel -and initramfs image must be located at the root of it !
Some UEFI systems don't allow to create more than one EFI STUB entry.
Unfortunately efibootmgr is not able to change EFI entries. You always have to delete/overwrite entries to make changes happen.
Please don't use this Bash script when you don't exactly know what you are doing here and what EFI STUB means.
You can get some great info at : https://wiki.archlinux.org/title/EFISTUB
And now good luck with EFI STUB booting.
L.Martens
Options:
-h, --help Display this help message
EOF
}
# Check if the script is running with root privileges
if [ "$UID" -ne 0 ]; then
echo "${RED}This script must be run with root privileges !${RESET}"
echo "type: sudo lusc -h for usage and more info."
exit 1
fi
# Parse command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h | --help)
usage
exit 0
;;
*)
echo "Unknown option: $1"
usage
exit 1
;;
esac
shift
done
# Prompt user to continue
echo "${BLUE}Welcome to LUSC - A Linux UEFI STUB Creator"
echo "-----------------------------------------"
echo "-----------------------------------------${RESET}"
read -r -p "Start creating UEFI boot entries ? (y/N) " choice
choice=$(echo "$choice" | tr '[:upper:]' '[:lower:]')
if [[ "$choice" != "y" ]]; then
echo "Goodbye.Exiting..."
exit 0
fi
# Prompt user to specify EFI partition
read -r -p "Please specify EFI partition (e.g., /dev/nvme0n1p1): " efi_partition
# Check if the EFI partition exists
if ! blkid | grep -q "$efi_partition"; then
echo "${RED}Error: EFI partition '$efi_partition' not found !${RESET}"
exit 1
fi
# Extract disk and partition number
efi_disk=$(echo "$efi_partition" | sed -E 's/p?[0-9]+$//')
efi_part_num=$(echo "$efi_partition" | grep -o '[0-9]*$')
# Prompt user to specify the label for the boot entry
read -r -p "Please specify the label for the boot entry (e.g., Arch Linux): " boot_label
# Detect partitions
efi_uuid=$(blkid -o value -s UUID "$efi_partition")
root_uuid=$(blkid -o value -s UUID "$(findmnt -no SOURCE /)")
# Check if swap partition exists
swap_uuid=$(blkid -o value -s UUID "$(findmnt -no SOURCE /swap)")
if [[ -z "$swap_uuid" ]]; then
echo "${GREEN}No swap partition detected. Assuming Zswap is used.${RESET}"
fi
# Default kernel parameters
default_params="root=UUID=$root_uuid rw"
if [[ -n "$swap_uuid" ]]; then
default_params="$default_params resume=UUID=$swap_uuid"
fi
# Prompt user to specify additional kernel parameters
echo "Current kernel parameters: $default_params"
echo "${GREEN}initrd and initrd-fallback will be added automatically !${RESET}"
echo "For example additional kernel parameters could be: quiet splash rootfstype=ext4 hostname=my-computer nohibernate noresume vm_debug=- ..."
read -r -p "Add additional kernel parameters (or press Enter to keep current): " extra_params
# Combine default and additional parameters
if [[ -n "$extra_params" ]]; then
kernel_params="$default_params $extra_params"
else
kernel_params="$default_params"
fi
# initramdisks with "\" !
initramdisk="\initramfs-linux.img"
initfallback="\initramfs-linux-fallback.img"
# Compose the command strings
linux_cmd="efibootmgr --create --disk $efi_disk --part $efi_part_num --label \"$boot_label\" --loader /vmlinuz-linux --unicode \"$kernel_params initrd=$initramdisk\" --verbose"
fallback_cmd="efibootmgr --create --disk $efi_disk --part $efi_part_num --label \"$boot_label (Fallback)\" --loader /vmlinuz-linux --unicode \"$kernel_params initrd=$initfallback\" --verbose"
# Print the commands for user confirmation
echo "Detected partitions:"
echo "EFI: $efi_partition ($efi_uuid)"
echo "Root: $(findmnt -no SOURCE /) ($root_uuid)"
if [[ -n "$swap_uuid" ]]; then
echo "Swap: $(findmnt -no SOURCE /swap) ($swap_uuid)"
resume_option="resume=UUID=$swap_uuid"
else
resume_option=""
fi
echo
echo "Composed commands:"
echo "$linux_cmd"
echo "$fallback_cmd"
# Prompt user to write or execute commands
read -r -p "Create executable only, create and execute (sets UEFI boot entries), or abort? (c/ce/a) " action
action=$(echo "$action" | tr '[:upper:]' '[:lower:]')
case "$action" in
c)
# Write commands to file
script_file="uefi_stub_gen_$(date "+%d-%-m-%Y--%H:%M")"
{
echo "#!/bin/bash"
echo "# Generated UEFI boot entries by LUSC"
echo "$fallback_cmd"
echo "$linux_cmd"
echo "exit 0"
echo "# See 'man efibootmgr' for more information"
} > "$script_file"
chmod +x "$script_file"
echo "Commands written to file: $script_file"
;;
ce)
# Write commands to file and execute
script_file="uefi_stub_gen_$(date "+%d-%-m-%Y--%H:%M")"
{
echo "#!/bin/bash"
echo "# Generated UEFI boot entries by LUSC"
echo "$fallback_cmd"
echo "$linux_cmd"
echo "exit 0"
echo "# See 'man efibootmgr' for more information"
} > "$script_file"
chmod +x "$script_file"
echo "Commands written to file: $script_file"
echo "Executing commands..."
"./$script_file"
echo "Changes written. Power off and restart (${RED}don't reboot !${RESET})."
;;
a)
echo "Aborted. No changes made."
;;
*)
echo "${RED}Invalid choice ! Aborting.${RESET}"
;;
esac
exit 0
My Script to easily create a working UEFI STUB bootentry. I tested it several times on different machines.
Feel free to adapt it to your special needs.
Last edited by EISENFELD (2024-05-17 15:38:05)
Ich weiß, dass ich nichts weiß !
Offline
Wireguard vpn toggler
package main
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
)
const (
conf = "/etc/wireguard/wg0.conf"
)
var (
on = []byte(`#AllowedIps = 10.111.222.0/24, fd2a:421:3819::/64
AllowedIPs = 0::/0, 0.0.0.0/0`)
off = []byte(`AllowedIps = 10.111.222.0/24, fd2a:421:3819::/64
#AllowedIPs = 0::/0, 0.0.0.0/0`)
)
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "try vpn on or off")
os.Exit(1)
}
confdata, err := os.ReadFile(conf)
if err != nil {
log.Fatal(err)
}
switch os.Args[1] {
case "on":
if bytes.Contains(confdata, on) {
fmt.Fprintln(os.Stderr, "vpn already on!")
os.Exit(1)
}
confdata = bytes.Replace(confdata, off, on, 1)
case "off":
if bytes.Contains(confdata, off) {
fmt.Fprintln(os.Stderr, "vpn already off!")
os.Exit(1)
}
confdata = bytes.Replace(confdata, on, off, 1)
default:
fmt.Fprintf(os.Stderr, "invalid command: %s\n", os.Args[1])
os.Exit(1)
}
err = os.WriteFile(conf, confdata, 0600)
if err != nil {
log.Fatal(err)
}
err = exec.Command("systemctl", "restart", "wg-quick@wg0.service").Run()
if err != nil {
log.Fatal(err)
}
}
Last edited by ugjka (2024-07-25 15:14:11)
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
Wireguard vpn toggler
Mind adding the language?
EDIT: Figured it out.
Last edited by Awebb (2024-07-25 19:14:54)
Online
It looks like that just adds/removes a single hash mark to a given line of a file. That could be a sed one-liner to really just toggle it, or perhaps just a few lines more to accept off/on parameters.
EDIT: E.g., completely untested as I don't have the relevant target file:
config=/path/to/target/file
case "$1" in
on) sed i '/AllowedIps/{s/^/#/;s/, #/,/}' $config ;;
off) sed i '/#AllowedIps/{s/^#//;s/, /, #/}' $config ;;
toggle) sed i '/#AllowedIps/{s/^#//;s/, /, #/;ba;};/AllowedIps/{s/^/#/;s/, #/,/;};:a' $config ;;
esac
# add systemctl restart ...
Last edited by Trilby (2024-07-25 19:37:25)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
A CLI snake game in C.
Dependency: ncurses
Compile: gcc main.c -o playsnake -lncurses
Run: ./playsnake
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#define MAX_LENGTH 100
#define SPEED 50000
#define SNAKE_CHAR '#'
#define FOOD_CHAR '0'
typedef struct {
int x, y;
} Point;
int maxx, maxy, food_x, food_y, score;
Point snake[MAX_LENGTH];
int length = 3;
enum direction { UP, DOWN, LEFT, RIGHT };
enum direction dir = RIGHT;
bool is_eaten = false;
void print_score()
{
attron(COLOR_PAIR(2));
mvprintw(maxy - 1, 0, "Score: %3d | Press esc to exit", score);
attroff(COLOR_PAIR(2));
}
void init_game() {
score = 0;
initscr();
cbreak();
noecho();
curs_set(0);
keypad(stdscr, TRUE);
nodelay(stdscr, TRUE);
start_color();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
init_pair(2, COLOR_WHITE, COLOR_BLACK);
init_pair(3, COLOR_RED, COLOR_BLACK);
init_pair(4, COLOR_GREEN, COLOR_BLACK);
init_pair(5, COLOR_YELLOW, COLOR_BLACK);
init_pair(6, COLOR_BLUE, COLOR_BLACK);
init_pair(7, COLOR_MAGENTA, COLOR_BLACK);
maxx = getmaxx(stdscr);
maxy = getmaxy(stdscr);
srand(time(NULL));
snake[0].x = maxx / 4;
snake[0].y = maxy / 2;
snake[1].x = snake[0].x - 1;
snake[1].y = snake[0].y;
snake[2].x = snake[1].x - 1;
snake[2].y = snake[1].y;
food_x = rand() % (maxx - 2) + 1;
food_y = rand() % (maxy - 2) + 1;
}
void draw_snake() {
attron(COLOR_PAIR(4));
for (int i = 0; i < length; i++) {
mvaddch(snake[i].y, snake[i].x, SNAKE_CHAR);
}
attroff(COLOR_PAIR(4));
}
void draw_food() {
attron(COLOR_PAIR(5));
mvaddch(food_y, food_x, FOOD_CHAR);
attroff(COLOR_PAIR(5));
}
void move_snake() {
for (int i = length - 1; i > 0; i--) {
snake[i] = snake[i - 1];
}
switch (dir) {
case UP:
snake[0].y--;
break;
case DOWN:
snake[0].y++;
break;
case LEFT:
snake[0].x--;
break;
case RIGHT:
snake[0].x++;
break;
}
// if snake reaches the edge, it will come from the other side
if(snake[0].x >= maxx)
{
snake[0].x = 1;
}
if(snake[0].x <= 0)
{
snake[0].x = maxx - 1;
}
if(snake[0].y >= maxy)
{
snake[0].y = 1;
}
if(snake[0].y <= 0)
{
snake[0].y = maxy - 1;
}
}
bool check_collision() {
for (int i = 1; i < length; i++) {
if (snake[i].x == snake[0].x && snake[i].y == snake[0].y) {
return true;
}
}
return false;
}
void check_food() {
if (snake[0].x == food_x && snake[0].y == food_y) {
is_eaten = true;
length++;
score += 10;
food_x = rand() % (maxx - 2) + 1;
food_y = rand() % (maxy - 2) + 1;
}
}
void handle_input() {
int ch = getch();
switch (ch) {
case KEY_UP:
if (dir != DOWN) dir = UP;
break;
case KEY_DOWN:
if (dir != UP) dir = DOWN;
break;
case KEY_LEFT:
if (dir != RIGHT) dir = LEFT;
break;
case KEY_RIGHT:
if (dir != LEFT) dir = RIGHT;
break;
case 27: // ESC
endwin();
exit(0);
default:
break;
}
}
void game_over() {
clear();
attron(COLOR_PAIR(3));
attron(A_BOLD);
mvprintw(maxy / 2, maxx / 2 - 40, "Game Over! Press ESC to exit. %d Points", score);
attroff(COLOR_PAIR(4));
attroff(A_BOLD);
score = 0;
length = 3;
dir = RIGHT;
refresh();
sleep(2);
}
int main() {
init_game();
while (true) {
clear();
print_score();
handle_input();
move_snake();
check_food();
draw_food();
draw_snake();
if (check_collision()) {
game_over();
init_game();
continue;
}
refresh();
usleep(SPEED);
}
endwin();
return 0;
}
For the smallest possible binary size, you can use "strip -s playsnake && upx -9 playsnake".
(UPX = Ultimate Packer for Executables)
Then this tiny command line game will be about 8,3 KB !
enjoy ;-)
Ich weiß, dass ich nichts weiß !
Offline
A CLI snake game in C.
I wrote the same sort of thing a few months ago, in March. I used C89.
#include <ncurses.h>
#include <unistd.h> /* usleep() */
#include <stdlib.h> /* rand() */
#include <time.h> /* To seed rand(). */
enum colour {
BACKGROUND = 1,
HEAD,
TAIL,
FOOD
};
int w, h; /* Width and height of game-space. */
int x, y, tx, ty; /* Head location, tail location. */
int surplus = 0; /* Extra length of tail to grow. Usually 0; 1 if food eaten. */
enum {UP, LEFT, DOWN, RIGHT} dir;
char *board; /* Bits 5-7 store type, 3-4 store direction. (Bit 0 is MSB). */
void draw_head(void){
const char dirs[] = "^<v>";
attron(COLOR_PAIR(HEAD));
mvaddch(y, x, dirs[dir]);
board[y * w + x] = HEAD | (dir<<3);
}
void undraw_head(void){ /* Turn snake's head into tail section. */
attron(COLOR_PAIR(TAIL));
mvaddch(y, x, '+');
board[y * w + x]++; /* Convert from HEAD (2) to TAIL (3). */
}
void retract_tail(void){
int tdir;
attron(COLOR_PAIR(BACKGROUND));
mvaddch(ty, tx, ' ');
tdir = board[ty * w + tx] >> 3;
board[ty * w + tx] = 0;
switch(tdir){
case UP: ty--; break;
case LEFT: tx--; break;
case DOWN: ty++; break;
case RIGHT: tx++; break;
}
}
void place_food(void){
int fx, fy;
do {
fx = rand() % w;
fy = rand() % h;
} while(board[fy * w + fx]);
attron(COLOR_PAIR(FOOD));
mvaddch(fy, fx, 'X');
board[fy * w + fx] = FOOD;
}
void turn(int new_dir){
dir = new_dir;
board[y * w + x] &= 7;
board[y * w + x] |= dir << 3;
draw_head();
}
int game_tick(void){
int nx = x, ny = y; /* New x,y. */
switch(dir){
case UP: ny--; break;
case LEFT: nx--; break;
case DOWN: ny++; break;
case RIGHT: nx++; break;
}
if(nx < 0 || nx >= w || ny < 0 || ny >= h)
return 1; /* GAME OVER; hit wall. */
if(board[ny * w + nx] == FOOD){
surplus++; /* sur+++ lol */
place_food();
} else if(board[ny * w + nx])
return 1; /* GAME OVER; hit self. */
undraw_head();
x = nx, y = ny;
draw_head();
if(surplus <= 0)
retract_tail();
else
surplus--;
attron(COLOR_PAIR(HEAD));
return 0;
}
void game_over(void){
int score;
for(score = 0;board[ty * w + tx]&7 != HEAD;score++)
retract_tail(), refresh(), usleep(100000);
endwin();
printf("SCORE: %d\n", score);
while(getch() != ERR)
; /* Prevent keypresses from reaching shell after exit. */
exit(0);
}
void game_loop(void){
while(1){
switch(getch()){
case KEY_UP: turn(UP); break;
case KEY_LEFT: turn(LEFT); break;
case KEY_DOWN: turn(DOWN); break;
case KEY_RIGHT: turn(RIGHT); break;
}
if(game_tick())
game_over(); /* Function does not return. */
usleep(1000000 / 20); /* 20FPS. */
}
}
void start_game(void){
board = calloc(w, h);
clear();
tx = x = rand() % w;
ty = y = rand() % h;
dir = rand() % 4;
draw_head();
place_food();
game_loop();
}
int main(){
srand(time(NULL));
initscr();
curs_set(0);
cbreak();
keypad(stdscr, TRUE);
nodelay(stdscr, TRUE);
noecho();
getmaxyx(stdscr, h, w);
start_color();
init_pair(BACKGROUND, COLOR_WHITE, COLOR_BLACK);
init_pair(HEAD, COLOR_YELLOW, COLOR_BLACK);
init_pair(TAIL, COLOR_GREEN, COLOR_BLACK);
init_pair(FOOD, COLOR_GREEN, COLOR_MAGENTA);
start_game();
endwin();
}
It's interesting to see the similarities and differences in how we did the same thing. We both had an enum for direction with the exact same members (in a different order), although unlike you I didn't bother to give it a name (which I think makes sense, since neither of us used it more than once). We both used "srand(time(NULL));" verbatim. The biggest difference is in how we encode the game environment.
Your snake is a set of (x,y) coordinates, and likewise for food. My game world, though, is a COLS*ROWS array covering the entire terminal. The game state is encoded almost entirely by this array. I probably had cellular automata on the mind. This has the effect that, unlike yours, my game doesn't write to incorrect memory locations when the snake is longer than 100 characters.
My first score (when I actually tried to play properly) was 1320. At 1000, I started noticing that getting a food item causes a blank space to appear in the snake, which remains until the tail moves past it. It seems to always first appear at the same amount of characters behind the head. It obviously has to do with MAX_LENGTH, but I have no idea how exactly it happens.
I don't think using ESC as an input key is a good idea, by the way. Some (all?) terminals seem to wait for a bit before allowing the keypress to go through; I think this is because it's used as an alternative to the ALT key. I changed it to 'q' and it became instant.
Using bare number literals for colours makes your code more confusing.
Also, yours flickers because you redraw the screen every time. And when food is collected, you increment the length, but you don't actually fill in the new position in snake[], so it defaults to (0,0), which means that for a brief moment, a snake tail section appears at the top left.
Also also in your game, food items can appear anywhere, including in the snake. And there's errant whitespace at the end of line 119 (my syntax highlighting makes this obvious).
It would be interesting to see if anyone else here has implemented the same thing.
"Don't comment bad code - rewrite it." - The Elements of Programming Style (1978), Brian W. Kernighan & P. J. Plauger, p. 144.
Offline
Your game is very well done, but the level of difficulty is much higher than mine. The snake dies when it hits the edge ;-)
Yes, the flickering is a problem, but I don't have that inside the terminal of VS Code. I just noticed this in the normal terminal.
There are still some problems in my code, you are right. I just started to code in C again after many years, so I am not very good, I still have to learn a lot...
I switched to GoLang some time ago and now back to good old C again.
Ich weiß, dass ich nichts weiß !
Offline
It looks like that just adds/removes a single hash mark to a given line of a file. That could be a sed one-liner to really just toggle it, or perhaps just a few lines more to accept off/on parameters.
EDIT: E.g., completely untested as I don't have the relevant target file:
config=/path/to/target/file case "$1" in on) sed i '/AllowedIps/{s/^/#/;s/, #/,/}' $config ;; off) sed i '/#AllowedIps/{s/^#//;s/, /, #/}' $config ;; toggle) sed i '/#AllowedIps/{s/^#//;s/, /, #/;ba;};/AllowedIps/{s/^/#/;s/, #/,/;};:a' $config ;; esac # add systemctl restart ...
Looks like some voodoo but that gave me the idea to write more correct version
package main
import (
"fmt"
"log"
"os"
"os/exec"
"regexp"
"slices"
)
const (
conf = "/etc/wireguard/wg0.conf"
)
var (
on = regexp.MustCompile(`(?mis)(#AllowedIPs).+(AllowedIPs).+`)
off = regexp.MustCompile(`(?mis)(AllowedIPs).+(#AllowedIPs).+`)
)
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "try vpn on or off")
os.Exit(1)
}
confdata, err := os.ReadFile(conf)
if err != nil {
log.Fatal(err)
}
switch os.Args[1] {
case "on":
if on.Match(confdata) {
fmt.Fprintln(os.Stderr, "vpn already on!")
os.Exit(1)
}
i := off.FindSubmatchIndex(confdata)
confdata = slices.Delete(confdata, i[4], i[4]+1)
confdata = slices.Insert(confdata, i[2], byte('#'))
case "off":
if off.Match(confdata) {
fmt.Fprintln(os.Stderr, "vpn already off!")
os.Exit(1)
}
i := on.FindSubmatchIndex(confdata)
confdata = slices.Insert(confdata, i[4], byte('#'))
confdata = slices.Delete(confdata, i[2], i[2]+1)
default:
fmt.Fprintf(os.Stderr, "invalid command: %s\n", os.Args[1])
os.Exit(1)
}
err = os.WriteFile(conf, confdata, 0600)
if err != nil {
log.Fatal(err)
}
err = exec.Command("systemctl", "restart", "wg-quick@wg0.service").Run()
if err != nil {
log.Fatal(err)
}
}
@Awebb it is go, yes
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
Since you've to restart the service anyway, why don't you just switch between wg-quick@wg0.service and wg-quick@wg0_novpn.service and use static configs instead of relying on string matches?
Offline
Since you've to restart the service anyway, why don't you just switch between wg-quick@wg0.service and wg-quick@wg0_novpn.service and use static configs instead of relying on string matches?
Ah yes, the voice of sanity! Well, i simply replicated what what i was doing by hand, that's all... I didn't really think it through, now did i?
https://ugjka.net
paru > yay | vesktop > discord
pacman -S spotify-launcher
mount /dev/disk/by-...
Offline
People are too busy to dodge systemd to actually use it :-D
Online