diff --git a/README.md b/README.md index 42d739f..f209032 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ ---*This project is still under heavy development!*--- +\Please do not delete this file, as it is used to display help information. + # L A C K A D A I S I C A L A collection of easy-to-understand, easy-to-use scripts, functions and aliases. Designed to be beginner-friendly but also useful! @@ -34,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, @@ -45,6 +45,25 @@ 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. + - SquashFS tools (mount/umount/make/destroy-squash-image): + 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 'make-squash-image' + 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: + > make-squash-image: Converts the folder into a hidden image + on the same disk as the folder. + > mount-squash-image: Sets up a mount for the XZ image alongside + directories for changes + > umount-squash-image: Self-explanatory. + > destroy-squash-image: 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. @@ -53,16 +72,32 @@ These are the included binaries and utilities: not exist yet. When the file appears on disk, the tool quits and simply returns the filename. This can be used in personal workflows to stall a longer - command that relies on the existence of said file. - - newday: - A basic but powerful journaling system. Recommended - to be set up via crontab. Can be used for everything - from diaries to general file storage to even BTRFS - snapshots. + command that relies on the existence of said file.= + - agenda: + Sets up a folder that is backed by a date-based tree + directory structure. Requires an argument for the name + of the folder to generate. Generates a symlink in this + name to a date sub-folder in a local '.daisy' folder. + Format is -> .daisy////. + Recommended to run via crontab - automatically cleans + up empty folders. + 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. - own: A simple utility. It's effectively an alias for "sudo chown -R user:user" on the target dir/file. Root permissions required! + - sshp: + This is a wrapper for `ssh`, the meaning of the 'p' is "Plus". + Integrates SSHFS support. If both client and host have SSHFS, + this wrapper can be used to connect their file systems. + For example, if you need to move files from one machine to + another, you could do something like this: + "sshp -m /:/mnt/pc -m /home/claire:/home/claire claire@pyon.net" + If privilege escalation is necessary for FS access, you will + be asked for a password. - shrc: This tool allows you to edit the RC file for your shell in your preferred editor. After saving, the @@ -74,11 +109,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 @@ -100,12 +135,27 @@ These are the included binaries and utilities: Like chsh but for your editor (EDITOR env). A list from which you can choose an installed editor (CLI or GUI) is shown. This list is by no means complete. + The editor for LACKADAISICAL and the global editor are + separate. If the EDITOR variable is already defined, + only LD_EDITOR will be changed. LD_EDITOR is the editor + used by LACKADAISICAL utilities. + To override the global EDITOR variable, pass "-g". + To restore the normal behavior of checking for an earlier + definition of EDITOR after passing "-g", run `ched` without + arguments. - cdf: Use fzf to find a file and then cd to its location. - cdp: Similar to `cdf` but uses tree+peco for the query. + - clip: + An extremely simple utility that functions as a clipboard of sorts. + To set the variable, run "clip " or provide data via stdin. + To get the variable, simply run clip without any arguments. + 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. @@ -120,7 +170,10 @@ These are the included binaries and utilities: decoded by passing the output(s) to `daisy_dec`. The output of `daisy_enc` can be concatenated with the output of another encoded file to create a multi-file - base64 archive similar to `daisy_enc_multi` + base64 archive similar to `daisy_enc_multi`. + Does not support symlinks yet, and will instead treat it + as a full input file (reads the data of the linked file). + When using stdin, please provide a filename as argument. - daisy_enc_multi: A version of `daisy_enc` that encodes multiple files and outputs `daisy_base64_data` blocks to a file @@ -155,5 +208,18 @@ These are the included binaries and utilities: `daisy_reload` - daisy_list: List all available commands without description. + - daisy_clear: + Removes all configuration, including aliases. + A backup is made and can be restored using "daisy_restore". + Triggers a reload. + - daisy_backup: + Backs up all config files. These can be restored using + "daisy_restore". + - daisy_restore: + Undoes "daisy_clear" by restoring config files. + Triggers a reload. + - ld_*: + All functions prefixed by "daisy_" are also available with + the prefix "ld_" via aliases provided in daisy.source. --- END OF DAISY HELP --- ``` diff --git a/newday b/agenda similarity index 54% rename from newday rename to agenda index 6266505..837cd0f 100755 --- a/newday +++ b/agenda @@ -1,25 +1,31 @@ -#!/bin/sh +#!/usr/bin/env bash # This script is intended to be run via cron. # It creates a folder structure in home for the current date in the following format: -# $HOME/ByDate/// +# $HOME//// -# It also sets up a symlink in home: $HOME/Today +# It also sets up a symlink for the tagged folder. # This symlink will always point to the folder for the current date. # Finally, it removes any folders without data, to prevent clutter. -# - Why did you make this? -# I remember things better when they have a date attached to them. -# You can use this for a primitive form of note-taking, but aside from notes - -# you can store any data this way. - LD_INTERNAL=1 . $(dirname $(realpath $0))/daisy.source -dir_name=ByDate -root_dir=$HOME/$dir_name -today_sym=$HOME/Today +if [[ $1 == '' ]]; then + echo "Usage: $LD_BIN " + echo "Creates a folder within '.daisy' in the current directory containing" + echo "a tree of dates associated with the folder name given by argument." + echo "A symlink is (re-)created at the same time with the same folder name." + echo "For example, if given the folder 'notes', this utility will:" + echo "- Create a folder '/.daisy/notes///'." + echo "- Create a symlink named 'notes' that points to it." + echo "It is recommended to run this via cron." + exit 1 +fi + +root_dir=$(dirname $1)/.daisy/$(basename $1) +today_sym=$1 # Present day today=$(date -I) @@ -29,7 +35,7 @@ day=$(echo $today | awk -F"-" '{print $3}') set -e -function errorFn() +function errorFn { error=$? if [[ $error -gt 0 ]]; @@ -49,6 +55,6 @@ test -L "$today_sym" && rm -rf "$today_sym" # Now we can set up today's directory mkdir -p "$root_dir/$year/$month/$day" -cd $root_dir -ln -s "./$dir_name/$year/$month/$day" "$today_sym" +ln -s "$root_dir/$year/$month/$day" "$today_sym" +ln -s "$root_dir" "$today_sym/.tree" exitcode=@? diff --git a/calm b/calm deleted file mode 100755 index 6e45689..0000000 --- a/calm +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# 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 d39446b..a380222 100755 --- a/cdz +++ b/cdz @@ -1,8 +1,8 @@ -#!/bin/sh +#!/usr/bin/env bash if [[ $LD_INTERNAL -ne 1 ]]; then - export LD_INTERNAL=1 + LD_INTERNAL=1 . $(dirname $(realpath $0))/daisy.source fi @@ -28,6 +28,7 @@ hasmounter=$? file "$target" 1>/dev/null exitcode=$? report=$(file "$target") +name=$(echo $@ | sed 's/:.*//' | sed 's|.*/||') # Check for archive type, supported types are zip/tar/rar comm1=(:) @@ -88,7 +89,7 @@ elif (( $israr == 0 )); then comm3=(exit 1) fi elif (( $hasmounter == 0 )); then - comm2=(archivemount "$target") + comm2=(archivemount -o allow_root -o use_ino "$target") comm4=(cd ..) comm5=(umount) fi @@ -101,18 +102,17 @@ dir=$(mktemp -d /tmp/extracted.XXXXXXXX) "${comm2[@]}" $dir "${comm3[@]}" -currentpath=$(realpath .) -cd $dir +currentpath=$(pwd) +sym="$currentpath/$name.tmp" +ln -f -s "$dir" "$sym" +cd "$sym" -# With archivemount, making a symlink will alter the archive -if (( $hasmounter == 1 )); then - ln -s $currentpath ./link-back - echo "A symlink to your original path has been created under the name \`link-back\`." - echo "You can use this to copy out files, but you can also just access your filesystem regularly." -fi +echo "A symlink has been made under the name \"$sym\"." +echo "This symlink points to the data directory \"$dir\"." echo "Type 'exit' to exit the extracted archive's folder and auto-delete it." eval $SHELL "${comm4[@]}" "${comm5[@]}" $dir rm -rf $dir +rm "$sym" diff --git a/daisy.source b/daisy.source index ade487f..c39ecba 100755 --- a/daisy.source +++ b/daisy.source @@ -1,4 +1,5 @@ -#!/bin/echo "This file can only be sourced, not run stand-alone." -- #!/bin/bash +#!/usr/bin/bash +#!/usr/bin/env -S echo "This file can only be sourced, not run stand-alone." # LACKADAISICAL SOURCE-ABLE FILE # Source this in your RC file or manually to receive some of the simpler @@ -11,11 +12,21 @@ # only included if sourced from one of the included scripts, though you are # free to bypass this by setting env variable LD_INTERNAL to 1. -if [[ $LD_INTERNAL -eq 1 ]]; +# Pass _LD_DEBUG=1 during sourcing to see debug information on a variety of things. + +if [[ $LD_INTERNAL == 1 ]]; then export LD_BIN=$(basename $0) fi +function ld_dbg +{ + if [[ $_LD_DEBUG == 1 ]]; + then + $@ + fi +} + # Variables for use in other utilities # Find the right argument for our folder arg=$0 @@ -25,17 +36,26 @@ then fi # Check for dependencies -function daisy_dependency_check +function _daisy_dependency_check { - command -v $1 1>/dev/null 2>/dev/null; + BIN=$(command -v $1 2>/dev/null) res=$? + echo $(($res ^ 1)) } -LD_HAS_fzf=$(daisy_dependency_check fzf) -LD_HAS_md5sum=$(daisy_dependency_check md5sum) -LD_HAS_peco=$(daisy_dependency_check peco) -LD_HAS_tree=$(daisy_dependency_check tree) +LD_HAS_fzf=$(_daisy_dependency_check fzf) +LD_HAS_md5sum=$(_daisy_dependency_check md5sum) +LD_HAS_peco=$(_daisy_dependency_check peco) +LD_HAS_tree=$(_daisy_dependency_check tree) +LD_HAS_dialog=$(_daisy_dependency_check dialog) + +ld_dbg echo "Presence of utils:" +ld_dbg echo fzf $LD_HAS_fzf +ld_dbg echo md5sum $LD_HAS_md5sum +ld_dbg echo peco $LD_HAS_peco +ld_dbg echo tree $LD_HAS_tree +ld_dbg echo dialog $LD_HAS_dialog export LD_FOLDER=$(dirname $(realpath $arg)) export LD_SOURCE_FILE=$(realpath $arg) @@ -57,11 +77,16 @@ 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 +ld_dbg echo "Sourced config contents:" +ld_dbg cat $LD_ALIASFILE +ld_dbg cat $LD_EDITORFILE + # Source everything in the config folder -function _daisy_source_configs +function _daisy_source_configs { for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`; do @@ -88,123 +113,8 @@ fi # FUNCTIONS and ALIASES ####################################################### ############################################################################### -# bak and unbak -function bak -{ - # Input: - target=$1 - - # Check if file exists - if ! test -f "$target"; - then - echo "Path not found: \"$target\"" - return 2 - fi - - # Handle both cases - if [[ $unbak_mode -eq 1 ]]; - then - cp -R "$target.bak" "$target" - rm -rf "$target.bak" - echo "Restored backup: $target <-- $target.bak" - else - cp -R "$target" "$target.bak" - echo "Backup made: $target --> $target.bak" - fi -} - -alias unbak="unbak_mode=1 bak" -alias lsa="ls -a -l -h" -alias lsn="ls -a -l -tu -r -h" -alias lss="ls -a -l -S -r -h" - -# Simple version of `cdf` -function cdf -{ - if [[ $LD_HAS_fzf != 1 ]]; - then - echo "This alias requires the utility 'fzf'. Please install it." - return 1 - fi - cd $(dirname $(fzf)) -} - -function cdp -{ - if [[ $LD_HAS_peco != 1 || $LD_HAS_tree != 1 ]]; - then - echo "This alias requires the utilities 'peco' and 'tree'. Please install them." - echo "Consider using 'cdf' instead." - return 1 - fi - cd $(dirname $(tree -fia --noreport . | peco)) -} - -function editpeco -{ - if [[ $LD_HAS_peco != 1 || $LD_HAS_tree != 1 ]]; - then - echo "This alias requires the utilities 'peco' and 'tree'. Please install them." - echo "Consider using 'cdf' instead." - return 1 - fi - tree --noreport -fia . | peco --prompt "Press CTRL+C to quit - query:" --exec "xargs -o -I{} $EDITOR {}" -} - -# for convenience purposes -function editbin -{ - editx $(which $1) -} - -# sets a new editor based on commony available ones, and some visual ones -function ched -{ - editors=("nano" "vim" "nvim" "vi" "emacs" "gedit" "kate" "mousepad" "micro" \ - "code" "subl" "joe" "kwrite" "gnome-text-editor") - - # Find which editors are installed - available_editors=() - for editor in "${editors[@]}"; - do - editor_real=$(command -v "$editor") - if command -v "$editor_real" >/dev/null 2>&1; - then - if [[ $(realpath "$EDITOR") == "$editor_real" ]]; - then - available_editors+=("$editor_real" "$editor (current choice)") - else - available_editors+=("$editor_real" "$editor") - fi - fi - done - - if [[ ! -z $@ ]]; - then - text="$@" - dialog --msgbox "$text" 0 0 - fi - - # Present all choices - choice=$(dialog --output-fd 1 --clear --title "Select Text Editor" \ - --menu "Choose one of the installed text editors:" 15 50 6 \ - "${available_editors[@]}") - dialog_ret=$? - - if [ $dialog_ret -ne 0 ]; - then - echo "No editor selected." - return - fi - - echo export EDITOR=$choice > "$LD_EDITORFILE" - echo export LD_EDITOR=$choice >> "$LD_EDITORFILE" - echo export LD_OLD_EDITOR=$EDITOR >>"$LD_EDITORFILE" - - _daisy_source_configs -} - -function wait_for_editor +# Undocumented but internally used +function daisy_wait_for_editor { pname="$1" fname="$2" @@ -223,32 +133,246 @@ function wait_for_editor done } +function mountcd +{ + cdpath="$@" + if [[ $cdpath == '' ]]; + then + \cd + fi + if [[ -f "$cdpath/.needs_mount" ]]; + then + mount-squash-image "$cdpath" + fi + \cd "$cdpath" +} + +alias cd=mountcd + +# Undocumented but internally used +function daisy_editor +{ + editor=${LD_EDITOR:-$EDITOR}; + ld_dbg echo Opening $editor to edit file: $1 + $editor "$1" + daisy_wait_for_editor $editor "$1" +} + +# bak and unbak +function bak +{ + # Input: + target=$1 + + # Check if file exists + if ! test -f "$target"; + then + echo "Path not found: \"$target\"" + return 2 + fi + + # Handle both cases + if [[ $unbak_mode == 1 ]]; + then + cp -R "$target.bak" "$target" + rm -rf "$target.bak" + echo "Restored backup: $target <-- $target.bak" + else + cp -R "$target" "$target.bak" + echo "Backup made: $target --> $target.bak" + fi +} + +function unbak +{ + unbak_mode=1 bak $@ +} + +function lsa +{ + ls -a -l -h $@ +} + +function lsn +{ + ls -a -l -tu -r -h $@ +} + +function lss +{ + ls -a -l -S -r -h $@ +} + +# Simple version of `cdf` +function cdf +{ + if [[ $LD_HAS_fzf != 1 ]]; + then + echo "This function requires the utility 'fzf'. Please install it." + return 1 + fi + cd "$(dirname "$(fzf)")" +} + +function cdp +{ + if [[ $LD_HAS_peco != 1 || $LD_HAS_tree != 1 ]]; + then + echo "This function requires the utilities 'peco' and 'tree'. Please install them." + echo "Consider using 'cdf' instead." + return 1 + fi + cd $(dirname $(tree -fia --noreport . | peco)) +} + +function editpeco +{ + if [[ $LD_HAS_peco != 1 || $LD_HAS_tree != 1 ]]; + then + echo "This function requires the utilities 'peco' and 'tree'. Please install them." + echo "Consider using 'cdf' instead." + return 1 + fi + tree --noreport -fia . | peco --prompt "Press CTRL+C to quit - query:" --exec "xargs -o -I{} $EDITOR {}" +} + +# for convenience purposes +function editbin +{ + editx $(which $1) +} + +# sets a new editor based on commony available ones, and some visual ones +function ched +{ + override=0 + if [[ $1 == "-g" ]]; + then + override=1 + fi + + if [[ $LD_HAS_dialog != 1 ]]; + then + echo "This function requires the utility 'dialog'. Please install it." + return 1 + fi + + editors=("nano" "vim" "nvim" "vi" "emacs" "gedit" "kate" "mousepad" "micro" \ + "code" "subl" "joe" "kwrite" "gnome-text-editor") + + # Find which editors are installed + available_editors=() + for editor in "${editors[@]}"; + do + editor_real=$(command -v "$editor") + if command -v "$editor_rmeal" >/dev/null 2>&1; + then + if [[ $(realpath "$EDITOR") == "$editor_real" ]]; + then + available_editors+=("$editor_real" "$editor (current)") + elif [[ $LD_EDITOR == "$editor_real" ]]; + then + available_editors+=("$editor_real" "$editor (LD choice)") + else + available_editors+=("$editor_real" "$editor") + fi + fi + done + + if [[ $override == 0 ]] && [[ ! -z $@ ]]; + then + text="$@" + dialog --msgbox "$text" 0 0 + elif [[ $override == 1 ]]; + then + text="You have passed '-g'. Your choice of dialog will override any other choice or setting of 'EDITOR'." + dialog --msgbox "$text" 0 0 + fi + + # Present all choices + choice=$(dialog --output-fd 1 --clear --title "Select Text Editor" \ + --menu "Choose one of the installed text editors:" 15 100 6 \ + "${available_editors[@]}") + dialog_ret=$? + + if [ $dialog_ret -ne 0 ]; + then + dialog --msgbox "No editor selected. Variables will not be updated." 0 0 + return 0 + fi + + [[ $override == 0 ]] && echo export EDITOR="${EDITOR:-$choice}" > "$LD_EDITORFILE" + [[ $override == 1 ]] && echo export EDITOR="$choice" > "$LD_EDITORFILE" + echo export LD_EDITOR="$choice" >> "$LD_EDITORFILE" + echo export LD_OLD_EDITOR="$EDITOR" >> "$LD_EDITORFILE" + + source "$LD_EDITORFILE" +} + function daisy_reload { - FROM_RC=0 source "$LD_SOURCE_FILE" + LD_INTERNAL=0 source "$LD_SOURCE_FILE" } function ldrc { - $EDITOR "$LD_SOURCE_FILE" - FROM_RC=0 source "$LD_SOURCE_FILE" + if [[ $1 == "-e" ]]; + then + daisy_editor "$LD_ESOURCEFILE" + else + daisy_editor "$LD_SOURCE_FILE" + fi + + LD_INTERNAL=0 source "$LD_SOURCE_FILE" } +enc_is_folder=0 function daisy_enc { - if [ -d $1 ]; + if [ -t 0 ] && [ -z "$1" ]; + then + echo "# $0: No arguments or stdin specified!" + return 1; + fi + + if [ ! -t 0 ] && [ -z "$1" ]; + then + echo "# $0: Please provide a filename as argument when using stdin" + return 1; + fi + + if [ -n "$1" ] && [ -d "$1" ]; then echo -e "daisy_create_folder=$1" else - file_info=$(file $1) - file_dir=$(dirname $1) - file_name=$(basename $1) + file_dir="" + file_name="" + perms=755 + + target=$1 + + # [TODO, FIX: An unknown bug is causing daisy_enc_folder to misbehave if stdin is accessed, so we disable it here.] + if [[ ! -t 0 ]] && [[ $enc_is_folder == 0 ]]; + then + file_dir="." + file_name="$1" + shift + elif [ -f "$1" ]; + then + file_dir=$(dirname "$1") + file_name=$(basename "$1") + perms=$(stat -c %a "$1") + else + echo "# $0: An error occured during encoding." + return 1 + fi base64_inner=$(cat ${1:-/dev/stdin} | base64 | tr -d '\n') # Print out our block echo -e "daisy_folder_$file_name=$file_dir" echo -e "daisy_data_base64_$file_name=\"$base64_inner\"" + echo -e "daisy_perms_$file_name=$perms" fi } @@ -272,13 +396,21 @@ function daisy_enc_folder cd "$dir" tree -fia --noreport . | sed 1d | while read -r item; do + enc_is_folder=1 daisy_enc "$item" + enc_is_folder=0 done } function daisy_dec { + if [ -t 0 ] && [ -z "$1" ]; + then + echo "$0: No arguments or stdin specified!" + return 1; + fi + data=$(cat ${1:-/dev/stdin} | grep -v "#" ) echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d } @@ -287,30 +419,48 @@ function daisy_dec # Extracts to the directory function daisy_dec_multi { - [[ ! -f $1 ]] && echo "daisy_dec_multi: No input file specified" && return - [[ ! -d $2 ]] && echo "daisy_dec_multi: No output directory specified" && return + arg1=$1 + arg2=$2 -folder= -while IFS= read -r line; do - if [[ "$line" == "daisy_create_folder="* ]]; + # Handle stdin support + if [ ! -t 0 ]; then - folder=$(echo $line | cut -d "=" -f 2) - mkdir -p "$2/$folder" + arg2=$1 + arg1=/dev/stdin fi - if [[ "$line" == "daisy_folder"* ]]; - then - folder=$(echo -e $line | cut -d "=" -f 2) - continue - fi + [[ -t 0 ]] && [[ ! -f $arg1 ]] && echo "daisy_dec_multi: No input file specified" && return + [[ ! -d $arg2 ]] && echo "daisy_dec_multi: No output directory specified" && return - if [[ "$line" == "daisy_data_base64"* ]]; - then - file=$(echo -e $line | cut -d "_" -f 4- | cut -d "=" -f 1) - daisy_dec <(echo $line) > "$2/$folder/$file" - fi + folder= + while IFS= read -r line; do + if [[ "$line" == "daisy_create_folder="* ]]; + then + folder=$(echo $line | cut -d "=" -f 2) + echo $folder + mkdir -p "$arg2/$folder" + fi - done <<< $(cat "$1") + if [[ "$line" == "daisy_folder"* ]]; + then + folder=$(echo -e $line | cut -d "=" -f 2) + continue + fi + + if [[ "$line" == "daisy_data_base64"* ]]; + then + file=$(echo -e $line | cut -d "_" -f 4- | cut -d "=" -f 1) + mkdir -p "$arg2/$folder" + daisy_dec <(echo $line) > "$arg2/$folder/$file" + fi + + if [[ "$line" == "daisy_perms"* ]]; + then + file=$(echo -e $line | cut -d "_" -f 3- | cut -d "=" -f 1) + perms=$(echo -e $line | cut -d "_" -f 3- | cut -d "=" -f 2) + chmod $perms "$arg2/$folder/$file" + fi + done <<< $(cat "$arg1") } # Saves a bit on typing @@ -320,6 +470,23 @@ function grab awk '{print $'$1'}' } +function clip +{ + data="" + + if [ ! -t 0 ]; then + data="$(cat)" + elif [ "$*" != "" ]; then + data="$*" + else + echo $LD_CLIP + return 0 + fi + + # Export the variable + export LD_CLIP="$data" +} + function daisy_unalias { unalias_param=$@ @@ -338,7 +505,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" } @@ -371,6 +538,60 @@ function daisy_alias source $LD_ALIASFILE } +function daisy_backup +{ + for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`; + do + bak "$f" + done +} + +function daisy_clear +{ + daisy_backup + + for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`; + do + echo "Removing config file: $f" + rm -rf "$f" + done + + echo "Config cleared. Use 'daisy_restore' if you would like to undo this." + daisy_reload +} + +function daisy_restore +{ + for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`; + do + unbak "$f" + bak "$f" 1>/dev/null + done + + echo "Config restored. Backups have been retained." + daisy_reload +} + +# Aliases for front-facing daisy_ functions +function _daisy_def_alias +{ + alias ld_$1=daisy_$1 +} + +_daisy_def_alias reload +_daisy_def_alias enc +_daisy_def_alias enc_multi +_daisy_def_alias enc_folder +_daisy_def_alias dec +_daisy_def_alias dec_multi +_daisy_def_alias alias +_daisy_def_alias unalias +_daisy_def_alias backup +_daisy_def_alias clear +_daisy_def_alias restore +_daisy_def_alias help +_daisy_def_alias list + _daisy_source_configs ############################################################################### @@ -380,32 +601,11 @@ _daisy_source_configs # End of user section! export LD_AVAILABLE=1 -# Start of internal section -function daisy_quit_if_no -{ - local dep_name="daisy_has_$1" - local has_dep="${!dep_name}" - - # Check first if we have checked for this dependency, if not, print a fixme! - # TODO: Remove upon release, or convert into self-modifying code. - if [[ -z "$has_dep" ]]; - then - echo "FIXME: Dependency `$1` should have an env variable, checking ad-hoc" - has_dep=$(daisy_dependency_check $1) - fi - - if [[ $has_dep -eq 0 ]]; - then - echo "$LD_BIN: The dependency $1 was not found! Please install it" \ - "to be able to use this utility!" - exit 1 - fi -} - [ -d "$LD_FOLDER" ] && export LD_AVAILABLE=1 # Help function, courtesy of Google Gemini -function daisy_help() { +function daisy_help() +{ local target_tool="$1" local file="$LD_FOLDER/README.md" @@ -466,7 +666,8 @@ function daisy_help() { } # Courtesy of Google Gemini -daisy_list() { +daisy_list() +{ local file="$LD_FOLDER/README.md" echo "Available LACKADAISICAL commands:" @@ -482,16 +683,3 @@ daisy_list() { } ' | sort } - -# Hide what we don't need -if [[ ! -v LD_INTERNAL ]]; -then - unset -f _daisy_source_configs - unset -f wait_for_editor - unset -f daisy_quit_if_no - unset -f daisy_dependency_check - unset LD_HAS_fzf - unset LD_HAS_peco - unset LD_HAS_md5sum - unset LD_HAS_tree -fi \ No newline at end of file diff --git a/destroy-squash-image b/destroy-squash-image new file mode 100755 index 0000000..dc4f3a3 --- /dev/null +++ b/destroy-squash-image @@ -0,0 +1,27 @@ +#!/bin/bash +DIR="$@" +DIR=$(readlink -f "$DIR") +DIR_SHORT=$(basename $DIR) + +if [[ -f "$DIR/.needs_mount" ]]; +then + echo "Not a SquashFS image, exiting." + exit 0 +fi + +echo "Destroying the existing SquashFS image." +echo "Copying data from the original directory." + +echo "Using rsync... in 2 seconds." +sleep 2 +rsync -avz --progress "$DIR" "/tmp/$DIR_SHORT.tmp" + +umount-squash-image "$DIR" + +rm -rf "$DIR" +mv "/tmp/$DIR_SHORT.tmp" "$DIR" + +rm -rf "$DIR/../.squashfs/$DIR_SHORT.img" +rm -rf "$DIR/../.squashfs/$DIR_SHORT" + +echo "Your SquashFS image was deleted." diff --git a/editx b/editx index 276209f..839dfd2 100755 --- a/editx +++ b/editx @@ -1,4 +1,4 @@ -# !/bin/sh +#!/usr/bin/env bash # This utility pre-allocs a file and adds execution permissions. It also # removes the resulting file if it is empty after the editor closes. diff --git a/filewait b/filewait index af52929..2705a43 100755 --- a/filewait +++ b/filewait @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # A simple utility that waits for a file to become available, infinitely LD_INTERNAL=1 diff --git a/make-squash-image b/make-squash-image new file mode 100755 index 0000000..4d33eeb --- /dev/null +++ b/make-squash-image @@ -0,0 +1,88 @@ +#!/bin/bash +# Lackadaisical squashfs tools +# Allows you to create a modifiable squashfs-backed image for a folder +BIN_DIR=$(dirname "$(readlink -f "$0")") +DIR=$1 + +test -d "$DIR" +if [[ $? -ne 0 ]]; then + echo Directory "$DIR" does not exist! + exit -1 +fi + +DIRSIZE=$(du -s "$DIR") + +DIR=$(readlink -f "$DIR") +DIR_SHORT=$(basename "$DIR") +echo Compressing "$DIR" + +# Make basic dirs +mkdir -p "${DIR}" +mkdir -p "${DIR_SHORT}" + +OVERLAY_ROOT=$(readlink -f "${DIR}/..")/.squashfs/${DIR_SHORT} +OVERLAY_UPPER=${OVERLAY_ROOT}/upper +OVERLAY_LOWER=${OVERLAY_ROOT}/lower +OVERLAY_WORK=${OVERLAY_ROOT}/work +OVERLAY_TARG=$DIR +RECREATE=false + +echo "Overlay information" +echo "=========================================================================" +echo "> DIR = \"$DIR\"" +echo "> DIR_SHORT = \"$DIR_SHORT\"" +echo "> OVERLAY_ROOT = \"$OVERLAY_ROOT\"" +echo "> OVERLAY_UPPER = \"$OVERLAY_LOWER\"" +echo "> OVERLAY_LOWER= \"$OVERLAY_UPPER\"" +echo "> OVERLAY_WORK = \"$OVERLAY_WORK\"" +echo "> OVERLAY_TARG = \"$OVERLAY_TARG\"" +echo "=========================================================================" + +# Make the dirs for the overlay +mkdir -p "$OVERLAY_ROOT" +mkdir -p "$OVERLAY_UPPER" +mkdir -p "$OVERLAY_LOWER" +mkdir -p "$OVERLAY_WORK" +mkdir -p "$OVERLAY_TARG" + +# Check for existing image +if test -f "${OVERLAY_ROOT}.img"; then + echo "We already have an existing image, updating i..." + RECREATE=true +fi + +sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz + +if [ $RECREATE == true ]; then + echo "Copy created, now unmount and swap everything." + sudo rm -rf "$OVERLAY_UPPER" + sudo rm -rf "$OVERLAY_LOWER" + sudo rm -rf "$OVERLAY_WORK" + rm -rf "${OVERLAY_ROOT}.img" +fi + +mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img" + +# Reset dir +sudo rm -rf "$DIR" +mkdir -p "$DIR" +touch "${DIR}/.needs_mount" + +echo "Your SquashFS-backed folder is ready for use." +echo "To mount it, either cd into it or use mount-squash-image." +echo "We recomnnend setting up a cronjob for that." +echo "" +echo "Should you wish to update the contents of the image with your changes made" +echo "imside of the folder, simply run make-squash-image again on the same" +echo "folder to update the imaghe." +echo +echo "To disable auto-mounting upon cd, pleas remove the" +echo "'.needs_mount' file to prevent that." +echo "To enable mount at-login, add something aking to this to cron:" +echo "\"@reboot /mount-squash-image \"" +echo +echo "=========================================================================" +echo "Storage data:" +echo "Uuncompressed: $DIRSIZE" +echo " Compressed: $(du -s ${OVERLAY_ROOT}.img)" +echo "=========================================================================" diff --git a/mount-squash-image b/mount-squash-image new file mode 100755 index 0000000..d2e065f --- /dev/null +++ b/mount-squash-image @@ -0,0 +1,20 @@ +#!/bin/bash +echo $@ + +DIR="$@" +DIR=$(readlink -f "$DIR") +DIR_SHORT=$(basename $DIR) +mkdir -p "$DIR" + +OVERLAY_ROOT=$(readlink -f "${DIR}/..")/.squashfs/${DIR_SHORT} +OVERLAY_UPPER=${OVERLAY_ROOT}/upper +OVERLAY_LOWER=${OVERLAY_ROOT}/lower +OVERLAY_WORK=${OVERLAY_ROOT}/work +OVERLAY_TARG=$DIR + +umount-squash-image $@ 1>/dev/null 2>/dev/null + +sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop +sudo mount -t overlay -o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK" none "$OVERLAY_TARG" + +echo "SquashFS filesystem is mounted and ready," diff --git a/own b/own index 9d59e2c..84cd6fe 100755 --- a/own +++ b/own @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Simple program that changes ownership to the current # user, recursively. @@ -14,4 +14,4 @@ then exit 2 fi -sudo chown -R $(whoami):$(whoami) $@ +sudo chown -R $(whoami):$(whoami) "$@" diff --git a/binbox b/scriptbox similarity index 58% rename from binbox rename to scriptbox index ec1e474..6aeb03d 100755 --- a/binbox +++ b/scriptbox @@ -1,5 +1,5 @@ -#!/bin/sh -# binbox: Creates a multi-binary script that self-contains the input scripts. +#!/usr/bin/env bash +# 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`. @@ -11,6 +11,7 @@ args=$@ function help() { echo "$LD_BIN is a utility that allows you to generate busybox-style combined binaries." + echo "It only supports shell scripts compatible with \`bash\`." echo "To access the original functionality of an input binary, you can either use a symlink or" echo "call the function like so: 'combi-bin input-bin ." echo "" @@ -55,32 +56,51 @@ i=0 b=0 s=0 p=0 + while [ $i -lt $# ]; do case "${args[$i]}" in -i) ((i++)) while [ $i -lt $# ] && [[ ! "${args[$i]}" =~ ^- ]]; do - inputs+=("${args[$i]}") + file="${args[$i]}" ((i++)) - ((b++)) + if [[ -e "$file" ]]; then + inputs+=("$file") + ((b++)) + else + echo "WARNING: Missing input binary: \"$file\"." + echo "Module will NOT be available!" + fi done continue ;; -s) ((i++)) while [ $i -lt $# ] && [[ ! "${args[$i]}" =~ ^- ]]; do - sources+=("${args[$i]}") + file="${args[$i]}" ((i++)) - ((s++)) + if [[ -e "$file" ]]; then + sources+=("$file") + ((s++)) + else + echo "WARNING: Missing input source: \"$file\"." + echo "File will NOT be sourced!" + fi done continue ;; -p) ((i++)) while [ $i -lt $# ] && [[ ! "${args[$i]}" =~ ^- ]]; do - includes+=("${args[$i]}") + file="${args[$i]}" ((i++)) - ((p++)) + if [[ -e "$file" ]]; then + includes+=("$file") + ((p++)) + else + echo "WARNING: Missing input include: \"$file\"." + echo "File will NOT be included!" + fi done continue ;; @@ -97,11 +117,6 @@ echo "Include files: ${includes[*]}" echo "Source files: ${sources[*]}" echo "Output binary: $output" -if [ "$b" -eq 0 ]; then - echo "Missing input binaries!" - exit 1 -fi - if [[ "$output" == "" ]]; then echo "Missing output file!" exit 1 @@ -112,11 +127,16 @@ function add() echo "$@" >> "$output" } +function add_nn() +{ + echo -n "$@" >> "$output" +} + rm -rf "$output" # Now to construct the binary # >>> Section 1, includes -add "#!/bin/bash" +add "#!/usr/bin/env bash" add "# Multi-call binary generated by LACKADAISICAL binbox" add "# $output information:" add "# Contained modules: ${inputs[*]}" @@ -135,6 +155,7 @@ for f in "${includes[@]}"; do add "$(cat "$f")" done +add "readarray -t all_funcs < <(declare -F | awk '{print \$3}')" # >>> Section 2: Modules for f in "${inputs[@]}"; do @@ -146,25 +167,52 @@ for f in "${inputs[@]}"; do done # >>> Section 3: Module selection +add "" +add "################################################################################" +add "# END OF INCLUDED MODULES ######################################################" +add "################################################################################" +add "" +add "# Array of modules as well as array of functions." +# Add a static list of modules with a no-newline add +add_nn "modules=(" + for f in "${inputs[@]}"; do + add_nn "\"$f\" " + done +add ")" +add 'mapfile -t funcs < <(printf "%s\n" "${all_funcs[@]}" "${modules[@]}" "${modules[@]}" | sort | uniq -u)' +add "" +add "# Check the export switches (-m and -f)" +add "" + add "symed=1" add "binself=\$(basename \$0)" -add "boxfile=\"$output\"" +add "boxfile=\"$(basename $output)\"" +add "" add "if [[ \$binself == \$boxfile ]]; then" add " symed=0" add " if [[ \$# -eq 0 ]]; then" -add " echo 'Available modules:'" - for f in "${inputs[@]}"; do - add " echo '$f'" - done +add " echo '$(basename $output): Multi-call binary generated by lackadaisical binbox.'" +add " echo 'Use switch \"-m\" to generate symlinks of modules in the current directory,'" +add " echo 'or use switch \"-f\" to generate symlinks of all available functions.'" +add " echo ''" +add " echo 'Exported modules:'" +add " for mod in \"\${modules[@]}\"; do" +add " echo \"- \$mod\"" +add " done" +add " echo ''" +add " echo 'Other functions:'" +add " for func in \"\${funcs[@]}\"; do" +add " echo \"- \$func\"" +add " done" add " exit 0" add " fi" add "fi" - +add "" add "if [[ \$symed -eq 0 ]]; then" add " eval \$@" add " exit \$?" add "fi" - +add "" add "if [[ \$symed -eq 1 ]]; then" add " eval \$(basename \$0) \$@" add "fi" diff --git a/shrc b/shrc index 4e0d0ee..485bfc7 100755 --- a/shrc +++ b/shrc @@ -1,4 +1,4 @@ -#!/bin/echo Please run this program with: ". shrc" or include +#!/usr/bin/env -S echo Please run this program with: ". shrc" or include # `FROM_RC=1 source shrc` in your RC file to set up an alias. # Just opens your .rc file easily, for your current shell @@ -10,37 +10,9 @@ then LD_INTERNAL=1 source $LD_SOURCE_FILE fi -function md5_opt() -{ - if [[ $daisy_has_md5sum -eq 1 ]]; - then - echo $(md5sum "$1" | awk '{print $1}') - fi -} +shellname=$(basename $SHELL) +rc_name="."$shellname"rc" +rc_path="$HOME/$rc_name" -if [[ $FROM_RC -eq 1 ]]; then - alias shrc=". shrc" -else - shellname=$(basename $SHELL) - rc_name="."$shellname"rc" - rc_path="$HOME/$rc_name" - - # Optional MD5 checks - has_changed=1 - sum1=$(md5_opt "$rc_path") - - # This sets a default if the variable does not exist. - EDITOR=${EDITOR:-$(ched)} - $EDITOR "$rc_path" - wait_for_editor $EDITOR "$rc_path" - - sum2=$(md5_opt "$rc_path") - - if [[ $daisy_has_md5sum -eq 1 && "$sum1" == "$sum2" ]]; - then - echo "The RC-file $rc_name has not changed on disk. Not sourcing." - return - fi - - source "$rc_path" -fi +daisy_editor "$rc_path" +source "$rc_path" diff --git a/sshp b/sshp new file mode 100755 index 0000000..eeedc7e --- /dev/null +++ b/sshp @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +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 +} + +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 +done + +if [[ ${#ssh_args[@]} -eq 0 ]] +then + usage +fi + +mount_logic="" +unmount_logic="" + +for map in "${mounts[@]}"; do + local_path="${map%%:*}" + remote_path="${map##*:}" + + if [[ "$local_path" != /* ]] + then + local_path="$PWD/$local_path" + fi + + 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; + " +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 + ${unmount_logic} + fi +" + +ssh -t -R ${remote_port}:localhost:22 "${ssh_args[@]}" "$remote_script" diff --git a/sw b/sw index 8427de3..0971413 100755 --- a/sw +++ b/sw @@ -1,7 +1,7 @@ -#!/bin/sh +#!/usr/bin/env bash # It just swaps two files -export LD_INTERNAL1 +LD_INTERNAL1 . $(dirname $(realpath $0))/daisy.source file1=$1 diff --git a/umount-squash-image b/umount-squash-image new file mode 100755 index 0000000..9eb0522 --- /dev/null +++ b/umount-squash-image @@ -0,0 +1,18 @@ +#!/bin/bash +DIR="$@" +DIR=$(readlink -f "$DIR") +DIR_SHORT=$(basename $DIR) +mkdir -p "$DIR" + +OVERLAY_ROOT=$(readlink -f "${DIR}/..")/.squashfs/${DIR_SHORT} +OVERLAY_UPPER=${OVERLAY_ROOT}/upper +OVERLAY_LOWER=${OVERLAY_ROOT}/lower +OVERLAY_WORK=${OVERLAY_ROOT}/work +OVERLAY_TARG=$DIR + +sudo umount -R "$OVERLAY_ROTO" +sudo umount -R "$OVERLAY_LOWER" +sudo umount -R "$OVERLAY_TARG" +sudo umount -R "$DIR" + +echo "SquashFS filesystem has been unmounted." diff --git a/what b/what index 0bf8c12..b4a470d 100755 --- a/what +++ b/what @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Where is the binary? # Usage: what [] # Returns: