Compare commits

...

6 commits

Author SHA1 Message Date
74ed7582f9 Small cosmetical changes 2026-03-15 19:11:37 +01:00
10d81b7e5b Added cdz check parameter for use in multicd (normal cd, squash cd and cdz).
Consolidated all squash functionality into a binary (squasher)
Updated the 'cd' alias (multicd).
Added -e to ldrc (to edit the user scripts)
2026-03-15 18:52:13 +01:00
83324dd0f7 After gemini-propoesed fixes 2026-03-13 01:38:34 +01:00
2e31283b61 Pre-refactor 2026-03-13 00:37:28 +01:00
84f55f82b8 Merge branch 'master' of https://git.lea.engineering/natrox/lackadaisical 2026-03-08 21:02:48 +01:00
eb0aab1613 Latest version 2026-03-08 20:54:07 +01:00
11 changed files with 426 additions and 238 deletions

View file

@ -36,8 +36,6 @@ lackadaisical` if you so desire.
To read this notice again, call the function 'daisy_help'.
===============================================================================
These are the included binaries and utilities:
- calm:
Reduce a process 'niceness' to 0.
- cdz:
This utility extracts an archive to /tmp and changes
directory to it in a new shell instance. Upon exit,
@ -47,6 +45,27 @@ These are the included binaries and utilities:
NO_ARCHIVEMOUNT=1. The standard script supports zip,
tarballs, and rar archives. We recommend relying on
archivemount` if you have it installed.
Use "--check" to only check if a file is an archive.
It returns 0 if it is, 1 otherwise.
- squasher:
These convenient set of tools allow you to easily create
XZ-compressed SquashFS images from existing folders to save
disk space. The resulting folder is still writable since it is
mounted using an 'overlay' system. You can use 'squasher make'
to compresses an existing folder. These folders are automatically
mounted when you use 'cd' to navigate to them (via an alias).
When using 'make-squash-image' on an already mounted folder, it will
instead update the existing image. As of writing, we do not have a
SystemD service to auto-mount, however, you cam easily add auto-mount
as a cron job. Here is a list of tools, they all take the same
folder argument:
> squasher make: Converts the folder into a hidden image
on the same disk as the folder.
> squasher mount: Sets up a mount for the XZ image alongside
directories for changes
> squasher umount: Self-explanatory.
> squasher destroy: Extracts the image and essentially reverts
everything. File changes are kept, however.
- editx:
Uses your standard CLI editor to create/modify a
file and make it executable.
@ -64,7 +83,7 @@ These are the included binaries and utilities:
Format is <dir> -> .daisy/<dir>/<year>/<month>/<day>.
Recommended to run via crontab - automatically cleans
up empty folders.
A symlink to the base of the folder's tree, ".tree",
A symbolic link to the base of the folder's tree, ".tree",
is created in the root of the specified directly.
Can be used for everything you'd like to sort by date.
For example; a diary, browser downloads, backups, code.
@ -92,11 +111,11 @@ These are the included binaries and utilities:
This is a tool similar to which and others, the key
difference is that it returns partial matches. It can
be used to search for binaries.
- binbox:
- scripbox:
This tool can be used to pack bash scripts into one
big megascript, much like how `busybox` works.
You can also make symlinks to it to invoke a specific
script (as of writing, 11/25, symlinks do not work well).
script.
- bak/unbak:
These small utilities make backups of files by making
a copy with a .bak suffix. Unbak reverses the process
@ -137,6 +156,8 @@ These are the included binaries and utilities:
The variable is stored locally in the shell as "LD_CLIP".
- ldrc:
Edits daisy.source and re-sources it, similarly to shrc.
Append "-e" to edit "extra.src", to add custom functions in the
lackadaisical namespace.
- daisy_reload:
Re-sources daisy.source. Essentially `ldrc` without
editing.

12
agenda
View file

@ -28,10 +28,7 @@ root_dir=$(dirname $1)/.daisy/$(basename $1)
today_sym=$1
# Present day
today=$(date -I)
year=$(echo $today | awk -F"-" '{print $1}')
month=$(echo $today | awk -F"-" '{print $2}')
day=$(echo $today | awk -F"-" '{print $3}')
read year month day < <(date "+%Y %m %d")
set -e
@ -50,11 +47,10 @@ function errorFn
trap errorFn ERR
# First we clear out empty folders, and remove the symlink if it exists
test -e "$root_dir" && find "$root_dir" -maxdepth 3 -type d -empty -print | xargs rm -rf
test -L "$today_sym" && rm -rf "$today_sym"
test -e "$root_dir" && find "$root_dir" -maxdepth 3 -type d -empty -delete
# Now we can set up today's directory
mkdir -p "$root_dir/$year/$month/$day"
ln -s "$root_dir/$year/$month/$day" "$today_sym"
ln -sf "$root_dir/$year/$month/$day" "$today_sym"
ln -s "$root_dir" "$today_sym/.tree"
exitcode=@?
exitcode=$?

41
calm
View file

@ -1,41 +0,0 @@
#!/usr/bin/env bash
# Calm a process down
# NEEDS_WORK: cleanup
# calm <pid> == only one process
# calm <bin> == all processes that match query
# calm * == if used in proc or a folder with just PID files, if not you will get an error
# calm <pid> <bin> .... OK
# set's NICE value to 0
# need sudo
LD_INTERNAL=1
. $(dirname $(realpath $0))/daisy.source
pids=$@
errorFn()
{
echo calm: Invalid operation or no such PID/process \(\"$(echo "$pids" | tr '\n' ' ' | cut -c -20)...\"\)
exit
}
for pid in $pids
do
# Process to PID in elegant way
newpids=$(pidof "$pid")
if [ "$newpids" ]
then
binary=$pid
pid=$newpids
else
newbins=$pid
binary=$(ps -p "$pid" -o comm= 2>/dev/null )
if [ $? != 0 ]
then
errorFn
fi
fi
echo Calming down $pid \("$binary"\)...
sudo renice -n 0 -p $pid;
done

195
cdz
View file

@ -1,118 +1,151 @@
#!/usr/bin/env bash
# Usage: cdz [--check] <archive>
if [[ $LD_INTERNAL -ne 1 ]];
if [[ $LD_INTERNAL -ne 1 ]]
then
LD_INTERNAL=1
. $(dirname $(realpath $0))/daisy.source
fi
target=$1
is_archive()
{
local file="$1"
local mime_type=$(file --mime-type -b "$file")
if [[ $mime_type == *"tar"* || $file == *.tar* || $mime_type == "application/zip" || $mime_type == "application/x-rar" ]]
then
return 0
fi
if command -v archivemount >/dev/null 2>&1
then
local test_dir=$(mktemp -d /tmp/cdz_check.XXXXXXXX)
local result=1
if archivemount -o readonly "$file" "$test_dir" >/dev/null 2>&1
then
result=0
umount "$test_dir"
fi
rmdir "$test_dir"
return $result
fi
return 1
}
# Check if file exists
if [[ -z "$target" ]];
check_mode=0
if [[ "$1" == "--check" ]]
then
echo "No target specified."
check_mode=1
shift
fi
target=$1
if [[ -z "$target" ]]
then
if [[ $check_mode -eq 0 ]]
then
echo "No target specified."
fi
exit 1
fi
if ! test -f "$target";
if [[ ! -f "$target" ]]
then
echo "File not found: \"$target\""
if [[ $check_mode -eq 0 ]]
then
echo "File not found: \"$target\""
fi
exit 2
fi
# Check if archivemount is present
which archivemount 1>/dev/null 2>/dev/null
hasmounter=$?
target_abs=$(realpath "$target")
name=$(basename "$target")
file "$target" 1>/dev/null
exitcode=$?
report=$(file "$target")
name=$(echo $@ | sed 's/:.*//' | sed 's|.*/||')
if is_archive "$target_abs"
then
if [[ $check_mode -eq 1 ]]
then
exit 0
fi
else
if [[ $check_mode -eq 1 ]]
then
exit 1
fi
mime_type=$(file --mime-type -b "$target_abs")
echo "Unsupported archive type: $mime_type"
exit 1
fi
# Check for archive type, supported types are zip/tar/rar
# Proceed with extraction
has_archivemount=$(command -v archivemount >/dev/null 2>&1; echo $?)
if [[ $has_archivemount -eq 0 && $NO_ARCHIVEMOUNT -ne 1 ]]
then
use_mounter=1
else
use_mounter=0
fi
mime_type=$(file --mime-type -b "$target_abs")
comm1=(:)
comm2=(echo "Unsupported archive type$add: \"$target\"")
comm2=(echo "Unsupported archive type: $mime_type")
comm3=(:)
comm4=(:)
comm5=(:)
echo $report | grep "tar archive" 1>/dev/null
istar=$?
echo $report | grep "Zip archive" 1>/dev/null
iszip=$?
echo $report | grep "Android" 1>/dev/null
iszip=$?
echo $report | grep "RAR archive" 1>/dev/null
israr=$?
# TAR archives come in many forms, if none of our tests say it's tar
# ...but it looks like tar and barks like tar, let's take the shot.
# Seems to work fairly well for the record.
res=$(echo "$target" | grep ".tar")
if [[ $res != "" ]];
if [[ $use_mounter -eq 1 ]]
then
istar=0
echo "Using archivemount..."
comm2=(archivemount -o allow_root,use_ino "$target_abs")
comm4=(cd ..)
comm5=(umount)
elif [[ $mime_type == *"tar"* || $target_abs == *.tar* ]]
then
comm2=(tar xvf "$target_abs" -C)
elif [[ $mime_type == "application/zip" ]]
then
if command -v unzip >/dev/null 2>&1
then
comm2=(unzip -q "$target_abs" -d)
else
comm1=(echo "unzip is missing")
comm3=(exit 1)
fi
elif [[ $mime_type == "application/x-rar" ]]
then
if command -v unrar >/dev/null 2>&1
then
# unrar needs the directory as the last argument
comm2=(unrar x -idq "$target_abs")
else
comm1=(echo "unrar is missing")
comm3=(exit 1)
fi
fi
if [[ $NO_ARCHIVEMOUNT -eq 1 ]]; then
hasmounter=1
fi
if (( $hasmounter == 0 )); then
echo "We have \`archivemount\`, so we'll use that!"
echo "If you'd prefer we not use it, please specify NO_ARCHIVEMOUNT=1"
istar=1
iszip=1
israr=1
fi
# Now we set the right command
if (( $istar == 0 )); then
comm2=(tar xvf "$target" -C)
elif (( $iszip == 0 )); then
which unzip 1>/dev/null
exitcode=$?
if (( $exitcode == 0 )); then
comm2=(unzip -q "$target" -d)
else
comm1=(echo "The utility 'unzip' is missing, please install it")
comm3=(exit 1)
fi
elif (( $israr == 0 )); then
which unrar 1>/dev/null
exitcode=$?
if (( exitcode == 0 )); then
comm2=(unrar -i nul "$target")
else
comm1=(echo "The utility 'unrar' is missing, please install it")
comm3=(exit 1)
fi
elif (( $hasmounter == 0 )); then
comm2=(archivemount -o allow_root -o use_ino "$target")
comm4=(cd ..)
comm5=(umount)
fi
# Create the temp dir, usually
dir=$(mktemp -d /tmp/extracted.XXXXXXXX)
# And the rest of the commands
"${comm1[@]}"
"${comm2[@]}" $dir
if [[ ${comm2[0]} == "unrar" ]]
then
"${comm2[@]}" "$dir"
else
"${comm2[@]}" "$dir"
fi
"${comm3[@]}"
currentpath=$(pwd)
sym="$currentpath/$name.tmp"
ln -f -s "$dir" "$sym"
sym="$(pwd)/$name.tmp"
ln -sf "$dir" "$sym"
cd "$sym"
echo "A symlink has been made under the name \"$sym\"."
echo "This symlink points to the data directory \"$dir\"."
echo "Extracted to $dir (linked via $sym)"
echo "Type exit to finish."
echo "Type 'exit' to exit the extracted archive's folder and auto-delete it."
eval $SHELL
"${comm4[@]}"
"${comm5[@]}" $dir
rm -rf $dir
"${comm5[@]}" "$dir"
rm -rf "$dir"
rm "$sym"

View file

@ -24,7 +24,6 @@ function ld_dbg
then
$@
fi
echo
}
# Variables for use in other utilities
@ -38,10 +37,11 @@ fi
# Check for dependencies
function _daisy_dependency_check
{
BIN=$(command -v $1 2>/dev/null)
res=$?
echo $(($res ^ 1))
if command -v "$1" >/dev/null 2>&1; then
echo 1
else
echo 0
fi
}
LD_HAS_fzf=$(_daisy_dependency_check fzf)
@ -77,20 +77,22 @@ fi
# [LEA.TODO] Turn these into arrays
LD_ALIASFILE="$LD_CONFIG_FOLDER/aliases.src"
LD_EDITORFILE="$LD_CONFIG_FOLDER/editor.src"
LD_ESOURCEFILE="$LD_CONFIG_FOLDER/extra.src"
touch $LD_ALIASFILE
touch $LD_EDITORFILE
touch $LD_ESOURCEFILE
ld_dbg echo "Sourced config contents:"
ld_dbg cat $LD_ALIASFILE
ld_dbg cat $LD_EDITORFILE
ld_dbg cat $LD_ESOURCEFILE
# Source everything in the config folder
function _daisy_source_configs
{
for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`;
do
source "$f"
done
while IFS= read -r -d '' f; do
source "$f"
done < <(find "$LD_CONFIG_FOLDER" -name "*.src" -type f -print0)
}
# Installation into PATH
@ -123,7 +125,7 @@ function daisy_wait_for_editor
while true;
do
alive=$(ps aux | grep $fname | grep $pname)
alive=$(pgrep -f "$pname.*$fname")
if [[ $alive == "" ]]
then
break
@ -132,12 +134,37 @@ function daisy_wait_for_editor
done
}
function multicd
{
cdpath="$@"
if [[ $cdpath == '' ]]
then
\cd
return
fi
if cdz --check "$cdpath" >/dev/null 2>&1
then
cdz "$cdpath"
return
fi
if [[ -f "$cdpath/.needs_mount" ]]
then
squasher mount "$cdpath"
fi
\cd "$cdpath"
}
alias cd=multicd
# Undocumented but internally used
function daisy_editor
{
editor=${LD_EDITOR:-$EDITOR};
ld_dbg echo Opening $editor to edit file: $1
$editor "$1"
$editor "$1"
sleep 1
daisy_wait_for_editor $editor "$1"
}
@ -248,7 +275,7 @@ function ched
for editor in "${editors[@]}";
do
editor_real=$(command -v "$editor")
if command -v "$editor_rmeal" >/dev/null 2>&1;
if command -v "$editor_real" >/dev/null 2>&1;
then
if [[ $(realpath "$EDITOR") == "$editor_real" ]];
then
@ -299,8 +326,12 @@ function daisy_reload
function ldrc
{
daisy_editor "$LD_SOURCE_FILE"
LD_INTERNAL=0 source "$LD_SOURCE_FILE"
ARG=$1
SOURCE="$LD_SOURCE_FILE"
[[ "$ARG" == "-e" ]] && SOURCE="$LD_ESOURCEFILE"
daisy_editor "$SOURCE"
LD_INTERNAL=0 source "$SOURCE"
}
enc_is_folder=0
@ -483,7 +514,7 @@ function daisy_unalias
# Remove from aliases list
newdata=$(cat "$LD_ALIASFILE" | grep -v "alias $unalias_param")
bak "$LD_ALIASFILE" 1>/dev/null
[[ NO_BAK -lt 1 ]] && bak "$LD_ALIASFILE" 1>/dev/null
echo -e $newdata > "$LD_ALIASFILE"
}

13
editx
View file

@ -16,15 +16,12 @@ then
ched "EDITOR env variable not set! You will have to set it yourself in the next screen."
fi
exists=$(file "$1" >/dev/null && echo $?)
[[ -e "$1" ]] && existed=1 || existed=0
touch "$1"
chmod +x "$1"
$EDITOR "$1"
wait $!
size=$(du "$1" | cut -f 1)
chmod +x "$1"
daisy_editor "$1"
if [[ $size -eq 0 && $exists -ne 0 ]];
then
rm -rf "$1"
if [[ ! -s "$1" && $existed -eq 0 ]]; then
rm -f "$1"
fi

18
own
View file

@ -5,13 +5,19 @@
LD_INTERNAL=1
. $(dirname $(realpath $0))/daisy.source
if [[ $@ == '' ]];
then
echo "$LD_BIN: Used to quickly take ownership of files/folders."
echo "Requires sudo. If sudo is not installed, this tool will fai."
if [[ -z "$1" ]]; then
echo "$LD_BIN: Quickly take ownership of files/folders."
echo "Usage: $LD_BIN <folders or files>"
echo "Means: chown -R <youruser>:<youruser> <folders or files>"
echo "Requires sudo. If sudo is not installed, this tool will fail."
exit 2
fi
sudo chown -R $(whoami):$(whoami) $@
# Ensure all arguments exist before attempting chown
for target in "$@"; do
if [[ ! -e "$target" ]]; then
echo "Error: \"$target\" does not exist."
exit 1
fi
done
sudo chown -R "$(whoami):$(whoami)" "$@"

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# binbox: Creates a multi-binary script that self-contains the input scripts.
# scriptbox: Creates a multi-binary script that self-contains the input scripts.
# Symlinking to the resulting binary with the name of one of the original scripts will trigger
# said script. The idea is similar to `busybox`.

179
squasher Executable file
View file

@ -0,0 +1,179 @@
#!/bin/bash
# Lackadaisical squashfs tools - Squasher
# Combined utility for make, mount, umount, and destroy operations.
BIN_DIR=$(dirname "$(readlink -f "$0")")
COMMAND="$1"
DIR="$2"
usage() {
echo "Usage: $0 {make|mount|umount|destroy} <directory>"
exit 1
}
if [[ -z "$COMMAND" || -z "$DIR" ]]; then
usage
fi
DIR=$(readlink -f "$DIR")
DIR_SHORT=$(basename "$DIR")
OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT"
OVERLAY_UPPER="$OVERLAY_ROOT/upper"
OVERLAY_LOWER="$OVERLAY_ROOT/lower"
OVERLAY_WORK="$OVERLAY_ROOT/work"
OVERLAY_TARG="$DIR"
case "$COMMAND" in
make)
if [[ ! -d "$DIR" ]]; then
echo "Error: Directory \"$DIR\" does not exist!"
exit 1
fi
echo "Checking system requirements (FUSE, SquashFS, OverlayFS)..."
for fs in fuse squashfs overlay; do
if ! grep -q "$fs" /proc/filesystems; then
echo "Attempting to load $fs module..."
sudo modprobe "$fs" || { echo "Error: $fs is not supported."; exit 1; }
fi
done
DIRSIZE=$(du -sh "$DIR" | cut -f1)
RECREATE=false
mkdir -p "$OVERLAY_ROOT"
if [[ -f "${OVERLAY_ROOT}.img" ]]; then
echo "Existing image found, updating..."
"$0" mount "$DIR"
DIRSIZE=$(du -sh "$DIR" | cut -f1)
RECREATE=true
fi
echo "Compressing \"$DIR\"..."
sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz || exit 1
if [[ "$RECREATE" == "true" ]]; then
echo "Cleaning up old layers..."
"$0" umount "$DIR"
if [[ -n "$OVERLAY_ROOT" && "$OVERLAY_ROOT" != "/" ]]; then
sudo rm -rf "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK"
rm -f "${OVERLAY_ROOT}.img"
fi
fi
mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img"
mkdir -p "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" "$OVERLAY_TARG"
sudo rm -rf "$DIR"
mkdir -p "$DIR"
touch "$DIR/.needs_mount"
echo "-------------------------------------------------------------------------"
echo "Storage Stats:"
echo " Original size: $DIRSIZE"
echo " Compressed: $(du -sh "${OVERLAY_ROOT}.img" | cut -f1)"
echo "-------------------------------------------------------------------------"
SERVICE_CONTENT="[Unit]
Description=SquashFS Mount for %I
After=local-fs.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=${BIN_DIR}/squasher mount %I
ExecStop=${BIN_DIR}/squasher umount %I
[Install]
WantedBy=multi-user.target"
echo "$SERVICE_CONTENT" | sudo tee /etc/systemd/system/squash-mount@.service > /dev/null
sudo systemctl daemon-reload
ESC_PATH=$(systemd-escape -p "$DIR")
SERVICE_NAME="squash-mount@$ESC_PATH.service"
read -p "Enable auto-mount service ($SERVICE_NAME)? [y/N] " yn
if [[ "$yn" =~ ^[Yy]$ ]]; then
sudo systemctl enable --now "$SERVICE_NAME"
sudo systemctl stop "$SERVICE_NAME"
sudo systemctl start "$SERVICE_NAME"
else
echo "Manual mount command: sudo systemctl start $SERVICE_NAME"
fi
;;
mount)
if [[ ! -f "${OVERLAY_ROOT}.img" ]]; then
echo "Error: SquashFS image \"${OVERLAY_ROOT}.img\" not found." >&2
exit 1
fi
"$0" umount "$DIR" 2>/dev/null
mkdir -p "$OVERLAY_LOWER"
sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop
if [[ $? -ne 0 ]]; then
echo "Error: Failed to mount squashfs image." >&2
exit 1
fi
sudo mount -t overlay none "$OVERLAY_TARG" \
-o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK"
if [[ $? -ne 0 ]]; then
echo "Error: Failed to mount overlay." >&2
sudo umount "$OVERLAY_LOWER" 2>/dev/null
exit 1
fi
echo "SquashFS filesystem is mounted and ready."
;;
umount)
sudo umount -l -R "$OVERLAY_TARG" 2>/dev/null
sudo umount -l -R "$OVERLAY_LOWER" 2>/dev/null
if mountpoint -q "$OVERLAY_TARG" || mountpoint -q "$OVERLAY_LOWER"; then
echo "Warning: Filesystem is still mounted. Check for open processes."
exit 1
fi
echo "SquashFS filesystem has been unmounted."
;;
destroy)
if [[ ! -f "$DIR/.needs_mount" ]]; then
if ! mountpoint -q "$DIR"; then
echo "Error: $DIR is not a SquashFS directory."
exit 1
fi
fi
ESC_PATH=$(systemd-escape -p "$DIR")
SERVICE_NAME="squash-mount@$ESC_PATH.service"
echo "Disabling service ($SERVICE_NAME)..."
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null
sudo systemctl disable "$SERVICE_NAME" 2>/dev/null
echo "Ensuring image is mounted to preserve data..."
"$0" mount "$DIR" 1>/dev/null 2>/dev/null
echo "Destroying image and restoring data..."
TEMP_DIR=$(mktemp -d /tmp/squash-dest.XXXXXXXX)
sudo rsync -aX "$DIR/" "$TEMP_DIR/" || { echo "Error: Failed to copy data."; exit 1; }
"$0" umount "$DIR"
sudo rm -rf "$DIR"
sudo mv "$TEMP_DIR" "$DIR"
sudo rm -rf "$OVERLAY_ROOT" "${OVERLAY_ROOT}.img"
echo "Success: SquashFS image destroyed and data restored to \"$DIR\"."
;;
*)
usage
;;
esac

101
sshp
View file

@ -1,95 +1,58 @@
#!/usr/bin/env bash
# sshp ("SSH PLUS") from lackadaisical
mounts=()
ssh_args=()
remote_port=$((10000 + RANDOM % 10000))
local_user=$(whoami)
usage()
{
echo "sshp (\"SSH PLUS\") from lackadaisical."
echo "Accepts all standard SSH options (see man ssh)."
echo "Additionally, supports SSHFS mounts using a Docker-style syntax (-m)."
echo "Usage: sshp -m <local>:<remote> [user@]host [ssh_options]"
echo "Example: sshp -m /home/juli:/home/juli juli@juli.pyon"
exit 1
usage() {
echo "Usage: sshp -m <local>:<remote> [user@]host [ssh_options]"
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
-m)
if [[ -z "$2" ]]
then
echo "Error: -m requires argument"
exit 1
fi
mounts+=("$2")
shift 2
;;
*)
ssh_args+=("$1")
shift
;;
esac
case "$1" in
-m)
if [[ -z "$2" ]]; then echo "Error: -m requires argument"; exit 1; fi
mounts+=("$2")
shift 2
;;
*)
ssh_args+=("$1")
shift
;;
esac
done
if [[ ${#ssh_args[@]} -eq 0 ]]
then
usage
fi
[[ ${#ssh_args[@]} -eq 0 ]] && usage
mount_logic=""
unmount_logic=""
for map in "${mounts[@]}"; do
local_path="${map%%:*}"
remote_path="${map##*:}"
local_path="${map%%:*}"
remote_path="${map##*:}"
[[ "$local_path" != /* ]] && local_path="$PWD/$local_path"
if [[ "$local_path" != /* ]]
then
local_path="$PWD/$local_path"
fi
mount_logic+="
echo '>> Preparing mount: ${remote_path}';
mkdir -p \"${remote_path}\" 2>/dev/null || sudo mkdir -p \"${remote_path}\"
mount_logic+="
echo '>> Preparing mount: ${remote_path}';
if ! mkdir -p \"${remote_path}\" 2>/dev/null
then
sudo mkdir -p \"${remote_path}\"
fi
if ! sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user ${local_user}@localhost:\"${local_path}\" \"${remote_path}\" 2>/dev/null
then
echo ' (User mount failed, attempting escalation...)';
if ! sudo sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user,allow_other ${local_user}@localhost:\"${local_path}\" \"${remote_path}\"
then
echo ' ! Mount failed completely. Check permissions or keys.';
fi
else
echo ' > Mounted successfully.';
fi
"
unmount_logic+="
fusermount -u -z \"${remote_path}\" 2>/dev/null || sudo fusermount -u -z \"${remote_path}\" 2>/dev/null;
"
sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user ${local_user}@localhost:\"${local_path}\" \"${remote_path}\" 2>/dev/null || \
sudo sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user,allow_other ${local_user}@localhost:\"${local_path}\" \"${remote_path}\"
"
unmount_logic+="fusermount -u -z \"${remote_path}\" 2>/dev/null || sudo fusermount -u -z \"${remote_path}\" 2>/dev/null;"
done
remote_script="
if ! command -v sshfs >/dev/null 2>&1
then
echo 'WARNING: \"sshfs\" not found on remote host.'
echo '>> Skipping mounts, proceeding with shell only...';
echo '----------------------------------------------';
else
${mount_logic}
fi
${SHELL:-bash};
if command -v sshfs >/dev/null 2>&1
then
if ! command -v sshfs >/dev/null 2>&1; then
echo 'WARNING: \"sshfs\" not found on remote host.'
else
${mount_logic}
fi
\${SHELL:-bash};
${unmount_logic}
fi
"
ssh -t -R ${remote_port}:localhost:22 "${ssh_args[@]}" "$remote_script"

11
what
View file

@ -26,7 +26,10 @@
LD_INTERNAL=1
. $(dirname $(realpath $0))/daisy.source
pwd=/
all_bins=$(cd / && echo $PATH | sed 's/[:]/ /g' | xargs ls -A | grep -v ":" | sort | uniq)
output=$(printf '%s\n' "-n" $all_bins | grep -i "$1")
echo "$output"
all_bins=$(compgen -c | sort -u)
if [[ -n "$1" ]]; then
echo "$all_bins" | grep -i "$1"
else
echo "$all_bins"
fi