diff --git a/README.md b/README.md index 701b0da..aa0dc3d 100755 --- a/README.md +++ b/README.md @@ -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 -> .daisy////. 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. diff --git a/agenda b/agenda index 837cd0f..f89dd61 100755 --- a/agenda +++ b/agenda @@ -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=$? diff --git a/calm b/calm deleted file mode 100755 index cd4052e..0000000 --- a/calm +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash -# Calm a process down -# NEEDS_WORK: cleanup -# calm == only one process -# calm == 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 .... 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 diff --git a/cdz b/cdz index a380222..3b8d15a 100755 --- a/cdz +++ b/cdz @@ -1,118 +1,151 @@ #!/usr/bin/env bash +# Usage: cdz [--check] -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" diff --git a/daisy.source b/daisy.source index 2b109fe..915ab1b 100755 --- a/daisy.source +++ b/daisy.source @@ -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" } diff --git a/editx b/editx index 839dfd2..685a977 100755 --- a/editx +++ b/editx @@ -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 diff --git a/own b/own index 916c06e..6db1b49 100755 --- a/own +++ b/own @@ -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 " - echo "Means: chown -R : " + 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)" "$@" diff --git a/binbox b/scriptbox similarity index 98% rename from binbox rename to scriptbox index 214e50d..6aeb03d 100755 --- a/binbox +++ b/scriptbox @@ -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`. diff --git a/squasher b/squasher new file mode 100755 index 0000000..213181d --- /dev/null +++ b/squasher @@ -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} " + 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 diff --git a/sshp b/sshp index eeedc7e..8f5c5c5 100755 --- a/sshp +++ b/sshp @@ -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 : [user@]host [ssh_options]" - echo "Example: sshp -m /home/juli:/home/juli juli@juli.pyon" - exit 1 +usage() { + echo "Usage: sshp -m : [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" diff --git a/what b/what index b4a470d..707e0ce 100755 --- a/what +++ b/what @@ -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