Refactor of parts of package manager, move ttyd to package manager, move check-service-status to utils

This commit is contained in:
nagumii 2025-02-07 21:51:38 +02:00
parent af9b7b42bd
commit 038da36ccd
14 changed files with 357 additions and 169 deletions

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016-2025 Shuanglei Tao <tsl0922@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -16,23 +16,6 @@ pause() {
read -n 1 -s -r
}
# Dialog uses a different method to display colors, and is limited to only these 8.
replace_colors() {
input="$1"
input="${input//$(echo -e '\033[0;30m')/\\Z0}" # black
input="${input//$(echo -e '\033[0;31m')/\\Z1}" # red
input="${input//$(echo -e '\033[0;32m')/\\Z2}" # green
input="${input//$(echo -e '\033[0;33m')/\\Z3}" # yellow
input="${input//$(echo -e '\033[0;34m')/\\Z4}" # blue
input="${input//$(echo -e '\033[0;35m')/\\Z5}" # magenta
input="${input//$(echo -e '\033[0;36m')/\\Z6}" # cyan
input="${input//$(echo -e '\033[0;37m')/\\Z7}" # white
input="${input//$(echo -e '\033[7m')/\\Zr}" # invert
input="${input//$(echo -e '\033[4m')/\\Zu}" # underline
input="${input//$(echo -e '\033[0m')/\\Zn}" # reset
echo "$input"
}
loading() {
dialog --no-collapse --infobox "$1" 5 45
}
@ -68,8 +51,8 @@ ingest_data() { # usage: `ingest_data "command.sh -argument" key_width`
# Read the output from femto-meshtasticd-config.sh and store output_string
while IFS=':' read -r key value; do
# Trim leading/trailing spaces from key and value
key=$(replace_colors "$(echo "$key" | xargs)")
value=$(replace_colors "$(echo "$value" | xargs)")
key=$(femto-utils.sh -R "$(echo "$key" | xargs)")
value=$(femto-utils.sh -R "$(echo "$value" | xargs)")
if [[ -z "$key" && -z "$value" ]]; then
output_string+="---\n"
else
@ -170,7 +153,7 @@ networking_settings() {
;;
7) # Test internet connection)
loading "Testing internet connection..."
dialog --no-collapse --title "Internet connectivity test" --colors --msgbox "$(replace_colors "$(femto-network-config.sh -t)")" 9 40
dialog --no-collapse --title "Internet connectivity test" --colors --msgbox "$(femto-utils.sh -R "$(femto-network-config.sh -t)")" 9 40
;;
8)
return
@ -191,13 +174,12 @@ utilities() {
5 "Run USB configuration tool" "" \
6 "Run OEM luckfox-config" "" \
7 "Process viewer/manager" "" \
8 "Disable/enable web terminal" "" \
9 "Disable/enable logging" "" \
10 "Disable/enable activity LED" "" \
11 "Reboot" "" \
12 "Shutdown" "" \
8 "Disable/enable logging" "" \
9 "Disable/enable activity LED" "" \
10 "Reboot" "" \
11 "Shutdown" "" \
" " "" "" \
13 "Back to main menu" "" 3>&1 1>&2 2>&3)
12 "Back to main menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $utilities_choice in
@ -288,40 +270,11 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
;;
6) luckfox-config ;;
7) htop ;;
8)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking web terminal status..."
ttyd_state=$(replace_colors "$(femto-utils.sh -t "check")")
[[ $ttyd_state == *"running"* ]] && ttyd_state+="\nWeb terminal available at \Zuhttps://$(hostname).local:7681\Zn"
choice=$(dialog --no-collapse --colors --title "Web Terminal" --cancel-label "Back" --help-button --default-item "$choice" --item-help --menu "Current state: $ttyd_state" 14 58 2 \
$(if ! echo "$ttyd_state" | grep -q 'enabled and running'; then echo "Enable and start (default) x  "; fi) \
$(if echo "$ttyd_state" | grep -q 'enabled'; then echo "Disable and stop x  "; fi) \
$(if echo "$ttyd_state" | grep -q 'enabled'; then echo "Start/restart ttyd service x  "; fi) \
$(if echo "$ttyd_state" | grep -q 'enabled'; then echo "View detailed service status x  "; fi) \
" " "" "" \
"Return to previous menu" "x" "" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -eq 1 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
elif [ $exit_status -eq 2 ]; then # Help ("extra") button
dialog --no-collapse --colors --title "Web terminal help" --msgbox "Web terminal is a browser based terminal interface, and can be used as a replacement for an SSH client such as PuTTY.\nSSL encryption is provided by keys generated during first-boot. Your browser may give a warning (net::ERR_CERT_AUTHORITY_INVALID) about the self-signed encryption certificate. This is normal. In Chromium (Chrome, Edge) click \"Advanced\" and \"Continue to femtofox.local (unsafe)\".\n\nWeb terminal is provided by ttyd.\nLicense for ttyd: \`cat /opt/ttyd/license\`.\nFor more details, see: \Zuhttps://github.com/tsl0922/ttyd\Zn\n\nWeb terminal is enabled by default on Foxbuntu." 0 0
else
case $choice in
"Enable and start (default)") femto-utils.sh -t "enable" ;;
"Disable and stop") femto-utils.sh -t "disable" ;;
"Start/restart ttyd service") femto-utils.sh -t "start" ;;
"View detailed service status") dialog --no-collapse --title "ttyd service status" --msgbox "$(systemctl status ttyd)" 0 0 ;;
"Return to previous menu") break ;;
esac
fi
done
;;
9) # logging)
8) # logging)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking current logging status..."
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable logging to reduce SD card wear.\nCurrent state: $(replace_colors "$(femto-utils.sh -l "check")")" 14 50 2 \
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable logging to reduce SD card wear.\nCurrent state: $(femto-utils.sh -R "$(femto-utils.sh -l "check")")" 14 50 2 \
1 "Enable (default)" "" \
2 "Disable" "" \
" " "" "" \
@ -334,11 +287,11 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
esac
done
;;
10) # activity LED)
9) # activity LED)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking current activity LED status..."
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable the Activity LED to save power.\nCurrent state: $(replace_colors "$(femto-utils.sh -a "check")")" 14 50 2 \
choice=$(dialog --no-collapse --colors --title "Logging" --cancel-label "Back" --default-item "$choice" --item-help --menu "Before deploying a Femtofox, it is advisable to disable the Activity LED to save power.\nCurrent state: $(femto-utils.sh -R "$(femto-utils.sh -a "check")")" 14 50 2 \
1 "Enable (default)" "" \
2 "Disable" "" \
" " "" "" \
@ -351,21 +304,21 @@ $(ingest_data "femto-meshtasticd-config.sh -i" 15)" 0 0
esac
done
;;
11) # reboot)
10) # reboot)
dialog --no-collapse --title "$title" --yesno "Reboot now?\n\nTip: Reboot can also be triggered by long-pressing the BOOT button on the luckfox." 10 45
if [ $? -eq 0 ]; then #unless cancel/no
loading "Rebooting..."
femto-utils.sh -r
fi
;;
12) # shutdown)
11) # shutdown)
dialog --no-collapse --colors --title "$title" --yesno "Shut down now?\n\nTo power system back on, disconnect/reconnect power.\n\nThe system shutdown command prevents damage to the filesystem from power interrupts, but does not stop power consumption.\n\nTip: You can also shut down the Femtofox by pressing the BOOT button for 5 seconds or by running \`\Zusudo halt\Zn\`." 14 60
if [ $? -eq 0 ]; then #unless cancel/no
loading "Shutting down...\n\nPower consumption will not stop."
femto-utils.sh -s
fi
;;
13) return ;;
12) return ;;
esac
done
}
@ -376,15 +329,18 @@ set_lora_radio() {
while true; do
echo "Checking LoRa radio..."
#Display filename, if exists: $(files=$(ls /etc/meshtasticd/config.d/* 2>/dev/null) && [ -n "$files" ] && echo "\n\nConfiguration files in use:\n$files" | paste -sd, -))
choice=$(dialog --no-collapse --colors --cancel-label "Cancel" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(replace_colors "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 19 50 10 \
"Ebyte e22-900m30s" "(SX1262_TCXO)" "" \
choice=$(dialog --no-collapse --colors --cancel-label "Cancel" --default-item "$choice" --title "Meshtastic LoRa radio" --item-help --menu "Currently configured LoRa radio:\n$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -k)")$(ls -1 /etc/meshtasticd/config.d 2>/dev/null | paste -sd ', ' - | sed 's/^/ (/; s/$/)/; s/,/, /g' | grep -v '^ ()$')" 22 50 10 \
"Radio name:" "Configuration:" "" \
"" "" "" \
"Ebyte e22-900m30s" "(SX1262_TCXO)" "Included in Femtofox Pro" \
"Ebyte e22-900m22s" "(SX1262_TCXO)" "" \
"Ebyte e80-900m22s" "(SX1262_XTAL)" "" \
"Heltec ht-ra62" "(SX1262_TCXO)" "" \
"Seeed wio-sx1262" "(SX1262_TCXO)" "" \
"Waveshare sx126x-xxxm" "(SX1262_XTAL)" "" \
"Waveshare sx126x-xxxm" "(SX1262_XTAL)" "Not recommended due issues with sending longer messages" \
"AI Thinker ra-01sh" "(SX1262_XTAL)" "" \
"None" "(simulated radio)" "" \
"LoRa Meshstick 1262" "(meshstick-1262)" "USB based LoRa radio from Mark Birss. https://github.com/markbirss/MESHSTICK" \
"Simulated radio" "(none)" "" \
" " "" "" \
"Skip" "" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
@ -409,9 +365,12 @@ set_lora_radio() {
radio="sx1262_xtal"
;;
"AI Thinker ra-01sh")
radio="sx1262_xtal"
radio="femto_sx1262_xtal"
;;
"None")
"LoRa Meshstick 1262")
radio="lora-meshstick-1262"
;;
"Simulated radio")
radio="none"
;;
"Skip")
@ -429,7 +388,7 @@ legacy_admin() {
choice="" # zero the choice before loading the submenu
while true; do
loading "Getting current legacy admin state..."
choice=$(dialog --no-collapse --colors --title "Legacy Admin" --default-item "$choice" --help-button --item-help --menu "If the node you Femtofox needs to administer or be administered by is running 2.4.x or earlier, you should set this to Enabled.\n\nCurrent state: $(replace_colors "$(femto-meshtasticd-config.sh -p)")" 16 65 5 \
choice=$(dialog --no-collapse --colors --title "Legacy Admin" --default-item "$choice" --help-button --item-help --menu "If the node you Femtofox needs to administer or be administered by is running 2.4.x or earlier, you should set this to Enabled.\n\nCurrent state: $(femto-utils.sh -R "$(femto-meshtasticd-config.sh -p)")" 16 65 5 \
1 "Enable" "" \
2 "Disable (default)" "" \
" " "" "" \
@ -466,7 +425,7 @@ meshtastic_settings() {
local title="Meshtastic Settings"
while true; do
echo "Checking Meshtasticd service state..."
meshtastic_choice=$(dialog --no-collapse --colors --title "$title" --cancel-label "Back" --default-item "$meshtastic_choice" --item-help --menu "Meshtasticd service is $(replace_colors "$(femto-meshtasticd-config.sh -S)")$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Warning: using simulated radio\Zn')" 19 50 4 \
meshtastic_choice=$(dialog --no-collapse --colors --title "$title" --cancel-label "Back" --default-item "$meshtastic_choice" --item-help --menu "Meshtasticd service is $(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Warning: using simulated radio\Zn')" 19 50 4 \
1 "View node info" "" \
2 "View configuration URL & QR code" "" \
3 "Set new configuration URL" "" \
@ -580,14 +539,14 @@ meshtastic_settings() {
dialog --no-collapse --title "Meshtastic Connectivity Test" --yesno "Will send \"test\" to channel 0 and wait for acknowledgement. Will try up to 3 times.\n\nPerform test?" 10 45
if [ $? -eq 0 ]; then #unless cancel/no
dialog --no-collapse --infobox "Performing mesh connectivity test.\n\nThis may take a while..." 6 45
dialog --no-collapse --colors --title "Meshtasticd connectivity test" --msgbox "$(replace_colors "$(femto-meshtasticd-config.sh -w)")" 0 0
dialog --no-collapse --colors --title "Meshtasticd connectivity test" --msgbox "$(femto-utils.sh -R "$(femto-meshtasticd-config.sh -w)")" 0 0
fi
;;
7) #manage meshtasticd service)
choice="" # zero the choice before loading the submenu
while true; do
echo "Checking Meshtasticd service state..."
local service_state="$(replace_colors "$(femto-meshtasticd-config.sh -S)")"
local service_state="$(femto-utils.sh -R "$(femto-utils.sh -C "meshtasticd")")"
choice=$(dialog --no-collapse --colors --cancel-label "Back" --title "Meshtasticd Service" --default-item "$choice" --menu "Meshtasticd service is $service_state$(femto-meshtasticd-config.sh -k | grep -q 'simulated' && echo '\n\Z1Using simulated radio\Zn')" 17 52 5 \
"View detailed service status" "x" \
" " " " \
@ -601,7 +560,7 @@ meshtastic_settings() {
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
"View detailed service status")
loading "Getting Meshtasticd service status..."
echo "Getting Meshtasticd service status..."
dialog --no-collapse --title "Meshtasticd service status" --msgbox "$(systemctl status meshtasticd)" 0 0
;;
"Start/restart service")
@ -688,7 +647,7 @@ help_menu() {
5 "Back to Help Menu" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
case $choice in
1) dialog --no-collapse --title "Femtofox" --msgbox "$(femto-pinout.sh -f)" 43 68 ;;
1) dialog --no-collapse --title "Femtofox" --msgbox "$(femto-pinout.sh -f)" 42 68 ;;
2) dialog --no-collapse --title "Femtofox Zero" --msgbox "$(femto-pinout.sh -z)" 34 48 ;;
3) dialog --no-collapse --title "Femtofox Tiny" --msgbox "$(femto-pinout.sh -t)" 38 70 ;;
4) dialog --no-collapse --title "Luckfox Pico Mini" --msgbox "$(femto-pinout.sh -l)" 23 65 ;;
@ -697,7 +656,7 @@ help_menu() {
done
;;
3) #Femtofox licensing info - short)
dialog --no-collapse --title "Femtofox license" --msgbox "$(femto-license.sh -f)" 28 60
dialog --no-collapse --title "Femtofox license" --msgbox "$(femto-license.sh -f)" 31 65
;;
4) #Femtofox licensing info - long)
clear

View file

@ -146,11 +146,15 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do
eval $prepare
cp /etc/meshtasticd/available.d/femtofox/femtofox_SX1262_XTAL.yaml /etc/meshtasticd/config.d
systemctl restart meshtasticd
elif [ "$OPTARG" = "lora-meshstick-1262" ]; then
eval $prepare
cp /etc/meshtasticd/available.d/lora-meshstick-1262.yaml /etc/meshtasticd/config.d/femtofox_lora-meshstick-1262.yaml # ugly code for the special case of the meshstick, which is not femto. Allows it to be detected by femto scripts and removed if radio changes
systemctl restart meshtasticd
elif [ "$OPTARG" = "none" ]; then
eval $prepare
systemctl restart meshtasticd
else
echo "$OPTARG is not a valid option. Options are \`lr1121_tcxo\`, \`sx1262_tcxo\`, \`sx1262_xtal\`, \`none\` (simradio)"
echo "$OPTARG is not a valid option. Options are \`lr1121_tcxo\`, \`sx1262_tcxo\`, \`sx1262_xtal\`, \`lora-meshstick-1262\`, \`none\` (simradio)"
fi
;;
q) # Option -q (set config URL)
@ -220,17 +224,7 @@ while getopts ":higkl:q:uU:rR:aA:cpo:sM:Stwuxm" opt; do
fi
;;
S) # Option -S (Get Meshtasticd Service state)
if systemctl is-enabled meshtasticd &>/dev/null; then
if echo "$(systemctl status meshtasticd)" | grep -q "active (running)"; then
echo -e "\033[4m\033[0;34menabled and running\033[0m"
elif echo "$(systemctl status meshtasticd)" | grep -q "inactive (dead)"; then
echo -e "\033[4m\033[0;31menabled but not running\033[0m"
else
echo "unknown"
fi
else
echo -e "\033[4m\033[0;31mdisabled\033[0m"
fi
femto-utils.sh -C "meshtasticd" # this functionality has been moved
;;
t) # Option -t (stop Meshtasticd service)
systemctl stop meshtasticd

View file

@ -151,14 +151,14 @@ $wifi_settings"
hostnamectl set-hostname "$OPTARG"
systemctl restart avahi-daemon
echo "Regenerating web terminal ssl keys..."
femto-utils.sh -T
/usr/local/bin/packages/ttyd.sh -k
;;
\?) # Invalid option
\?) # Invalid option)
echo "Invalid option: -$OPTARG"
echo -e "$help"
exit 1
;;
:) # Missing argument for option
:) # Missing argument for option)
echo "Option -$OPTARG requires a setting."
echo -e "$help"
exit 1

View file

@ -69,7 +69,7 @@ femto-utils.sh -E
#generate ttyd SSL keys
log_message "Generating new Web Terminal SSL encryption keys. This can take a minute..."
femto-utils.sh -T
/usr/local/bin/packages/ttyd.sh -k
# prevent randomized mac address for eth0. If `eth0`` is already present in /etc/network/interfaces, skip
mac="$(awk '/Serial/ {print $3}' /proc/cpuinfo | tail -c 11 | sed 's/^\(.*\)/a2\1/' | sed 's/\(..\)/\1:/g;s/:$//')"

View file

@ -77,7 +77,6 @@ $(if $package_dir/$1.sh -O | grep -q 'D'; then echo "\n$($package_dir/$1.sh -D)"
$(echo "Currently: " && $package_dir/$1.sh -I && echo "\Zuinstalled\Zn" || echo "\Zunot installed\Zn")\n\
$(if output=$($package_dir/$1.sh -L); [ -n "$output" ]; then echo "Installs to: \Zu$output\Zn\n"; fi)\
$(if output=$($package_dir/$1.sh -C); [ -n "$output" ]; then echo "Conflicts with: \Zu$output\Zn\n"; fi)\
An internet connection is required for installation.\n\
$(if $package_dir/$1.sh -O | grep -q 'U'; then echo "\nFor more information, visit $($package_dir/$1.sh -U)"; fi)" 0 0
package_menu $1 # after user hits "OK", move on to package menu
}
@ -87,17 +86,18 @@ package_menu() {
while true; do
echo "Loading package menu..."
# for each line, check if it's supported by the package, display it if the current install state of the package is appropriate (example: don't display "install" if the package is already installed, don't display "stop service" for a package with no services)
choice=$(dialog --no-collapse --title "$title" --cancel-label "Back" --default-item "$choice" --menu "$($package_dir/$1.sh -N)" 18 45 5 \
service_state=$(femto-utils.sh -C "$($package_dir/$1.sh -E)")
choice=$(dialog --no-collapse --colors --title "$($package_dir/$1.sh -N)" --cancel-label "Back" --default-item "$choice" --menu "$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Service status: $(femto-utils.sh -R "$service_state")"; fi)" 18 45 5 \
$(if $package_dir/$1.sh -O | grep -q 'l' && $package_dir/$1.sh -I; then echo "Run software x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'i' && ! $package_dir/$1.sh -I; then echo "Install x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'u' && $package_dir/$1.sh -I; then echo "Uninstall x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'a' && $package_dir/$1.sh -I; then echo "Initialize x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'g' && $package_dir/$1.sh -I; then echo "Upgrade x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "Enable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'd' && $package_dir/$1.sh -I; then echo "Disable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 's' && $package_dir/$1.sh -I; then echo "Stop service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'r' && $package_dir/$1.sh -I; then echo "Start/restart service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Get service status x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ ! $service_state =~ "enabled" ]]; then echo "Enable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ ! $service_state =~ "disabled" ]]; then echo "Disable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ ! $service_state =~ "not running" ]] && [[ ! $service_state =~ "disabled" ]]; then echo "Stop service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I && [[ $service_state =~ "enabled" ]]; then echo "Start/restart service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Detailed service status x"; fi) \
" " "" \
"Back to software manager" "" 3>&1 1>&2 2>&3)
[ $? -eq 1 ] && break # Exit the loop if the user selects "Cancel" or closes the dialog
@ -112,14 +112,16 @@ package_menu() {
"Disable service") echo "Disabling and stopping service..." && eval "$package_dir/$1.sh -d" && eval "$package_dir/$1.sh -s" ;;
"Stop service") echo "Stopping service..." && eval "$package_dir/$1.sh -s" ;;
"Start/restart service") echo "Starting/restarting service..." && eval "$package_dir/$1.sh -r" ;;
"Get service status") echo "Getting service status..." && dialog --no-collapse --title "$title" --msgbox "$(eval "$package_dir/$1.sh -S")" 0 0 ;;
"Detailed service status") echo "Getting service status..." && dialog --no-collapse --title "$title" --msgbox "$(eval "$package_dir/$1.sh -S")" 0 0 ;;
"Back to software manager") break ;;
esac
done
}
# generate menu from filenames in /usr/local/bin/packages
while true; do
echo "Loading packages..."
menu_entries=("Package name" "Installed?" "" "")
index=1
for file in /usr/local/bin/packages/*.sh; do

View file

@ -19,9 +19,9 @@ Options are:
-o OS info
-S Storage & RAM info
-t "enable" Enable/disable/start/stop/check ttyd (web terminal). Options: "enable" "disable" "start" "stop" "check"
-T Generate/overwrite ttyd encryption keys
-E Generate/overwrite SSH encryption keys
-C "service" Check if service is enabled, disabled, running
-R "command" Replace colors for dialog menus
EOF
)
@ -95,7 +95,7 @@ os_info() {
local system_uptime="$(uptime -p | awk '{$1=""; print $0}' | sed -e 's/ day\b/d/g' -e 's/ hour\b/h/g' -e 's/ hours\b/h/g' -e 's/ minute\b/m/g' -e 's/ minutes\b/m/g' | sed 's/,//g')"
local kernel_active_modules="$(lsmod | awk 'NR>1 {print $1}' | tr '\n' ' ' && echo)"
local kernel_boot_modules="$(modules=$(sed -n '6,$p' /etc/modules | sed ':a;N;$!ba;s/\n/, /g;s/, $//'); [ -z "$modules" ] && echo "none" || echo "$modules")"
local ttyd_enabled="$(ttyd "check" | sed 's/\x1b\[[0-9;]*m//g')"
local ttyd_enabled="$(femto-utils.sh -C "ttyd")"
local logging_enabled="$(logging "check" | sed 's/\x1b\[[0-9;]*m//g')"
local act_led="$(femto-utils.sh -a "check" | sed -r 's/\x1B\[[0-9;]*[mK]//g')" #remove color from output
@ -201,41 +201,59 @@ logging() {
fi
}
ttyd() {
if [ "$1" = "disable" ]; then
systemctl disable ttyd
systemctl stop ttyd
echo "Disabled ttyd service."
exit 0
elif [ "$1" = "enable" ]; then
systemctl enable ttyd
echo "Enabled ttyd service."
systemctl start ttyd
exit 0
elif [ "$1" = "check" ]; then
if systemctl is-enabled ttyd &>/dev/null; then
if echo "$(systemctl status ttyd)" | grep -q "active (running)"; then
echo -e "\033[4m\033[0;34menabled and running\033[0m"
elif echo "$(systemctl status ttyd)" | grep -q "inactive (dead)"; then
echo -e "\033[4m\033[0;31menabled but not running\033[0m"
exit 1
else
echo "unknown"
fi
else
echo -e "\033[4m\033[0;31mdisabled\033[0m"
exit 1
fi
elif [ "$1" = "start" ]; then
echo "Starting/restarting ttyd service..."
systemctl restart ttyd
elif [ "$1" = "stop" ]; then
echo "Stopping ttyd service..."
systemctl stop ttyd
fi
# Dialog uses a different method to display colors, and is limited to only these 8.
replace_colors() {
input="$1"
input="${input//$(echo -e '\033[0;30m')/\\Z0}" # black
input="${input//$(echo -e '\033[0;31m')/\\Z1}" # red
input="${input//$(echo -e '\033[0;32m')/\\Z2}" # green
input="${input//$(echo -e '\033[0;33m')/\\Z3}" # yellow
input="${input//$(echo -e '\033[0;34m')/\\Z4}" # blue
input="${input//$(echo -e '\033[0;35m')/\\Z5}" # magenta
input="${input//$(echo -e '\033[0;36m')/\\Z6}" # cyan
input="${input//$(echo -e '\033[0;37m')/\\Z7}" # white
input="${input//$(echo -e '\033[7m')/\\Zr}" # invert
input="${input//$(echo -e '\033[4m')/\\Zu}" # underline
input="${input//$(echo -e '\033[0m')/\\Zn}" # reset
echo "$input"
}
while getopts ":harsl:ipcnoSt:TE" opt; do
# this has been moved to /usr/local/bin/packages/ttyd.sh under the aegis of femto_software.sh
# ttyd() {
# if [ "$1" = "disable" ]; then
# systemctl disable ttyd
# systemctl stop ttyd
# echo "Disabled ttyd service."
# exit 0
# elif [ "$1" = "enable" ]; then
# systemctl enable ttyd
# echo "Enabled ttyd service."
# systemctl start ttyd
# exit 0
# elif [ "$1" = "check" ]; then
# if systemctl is-enabled ttyd &>/dev/null; then
# if echo "$(systemctl status ttyd)" | grep -q "active (running)"; then
# echo -e "\033[4m\033[0;34menabled and running\033[0m"
# elif echo "$(systemctl status ttyd)" | grep -q "inactive (dead)"; then
# echo -e "\033[4m\033[0;31menabled but not running\033[0m"
# exit 1
# else
# echo "unknown"
# fi
# else
# echo -e "\033[4m\033[0;31mdisabled\033[0m"
# exit 1
# fi
# elif [ "$1" = "start" ]; then
# echo "Starting/restarting ttyd service..."
# systemctl restart ttyd
# elif [ "$1" = "stop" ]; then
# echo "Stopping ttyd service..."
# systemctl stop ttyd
# fi
# }
while getopts ":harsl:ipcnoSEC:R:" opt; do
case ${opt} in
h) # Option -h (help)
echo -e $help
@ -260,13 +278,6 @@ while getopts ":harsl:ipcnoSt:TE" opt; do
n) networking_info ;; # Option -n (Networing info)
o) os_info ;; # Option -o (OS info)
S) storage_info ;; # Option -S (Storage & RAM info)
t) ttyd $OPTARG ;; # Option -t (ttyd service manager)
T) # Option -T (new ttyd SSL keys)
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout /etc/ssl/private/ttyd.key -out /etc/ssl/certs/ttyd.crt -subj "/CN=$(hostname)" -addext "subjectAltName=DNS:$(hostname)"
chmod 600 /etc/ssl/private/ttyd.key
chmod 644 /etc/ssl/certs/ttyd.crt
systemctl restart ttyd
;;
E) # Option -E (new SSH encryption keys)
rm /etc/ssh/ssh_host_*
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
@ -276,6 +287,32 @@ while getopts ":harsl:ipcnoSt:TE" opt; do
chown root:root /etc/ssh/ssh_host_*
systemctl restart ssh
;;
C) # Option -C (Check service)
if systemctl is-enabled $OPTARG &>/dev/null; then
if echo "$(systemctl status $OPTARG)" | grep -q "active (running)"; then
echo -e "\033[4m\033[0;34menabled and running\033[0m"
exit 0
elif echo "$(systemctl status $OPTARG)" | grep -q "inactive (dead)"; then
echo -e "\033[4m\033[0;31menabled but not running\033[0m"
exit 1
elif echo "$(systemctl status $OPTARG)" | grep -q "failed"; then
echo -e "\033[4m\033[0;31menabled but failed\033[0m"
exit 1
elif echo "$(systemctl status $OPTARG)" | grep -q "activating"; then
echo -e "\033[4m\033[0;31menabled, activating\033[0m"
exit 2
else
echo "unknown"
exit 2
fi
else
echo -e "\033[4m\033[0;31mdisabled\033[0m"
exit 1
fi
;;
R)
replace_colors "$OPTARG"
;;
\?) # Unknown option)
echo -e "Unknown argument $1.\n$help"
;;

View file

@ -33,6 +33,7 @@ Arguments:
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service name
-L Get Install location
-C Get Conflicts
-I Check if installed. Returns an error if not installed
@ -53,7 +54,7 @@ name="Meshing Around" # software name
author="Spud" # software author - OPTIONAL
description="Meshing Around is a feature-rich bot designed to enhance your Meshtastic network experience with a variety of powerful tools and fun features. Connectivity and utility through text-based message delivery. Whether you're looking to perform network tests, send messages, or even play games, mesh_bot.py has you covered." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/SpudGunMan/meshing-around" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuagedsrNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiuagedsrNADUOSELCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="mesh_bot pong_bot mesh_bot_reporting" # the name of the service, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/meshing-around" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -166,6 +167,9 @@ while getopts ":h$options" opt; do
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)

View file

@ -32,6 +32,7 @@ Arguments:
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service name
-L Get install location
-P Get package name
-C Get Conflicts
@ -54,7 +55,7 @@ name="Mosquitto MQTT Broker" # software name
author="Eclipse Foundation" # software author - OPTIONAL
description="Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.\n\nThe MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.\n\nThe Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.\n\nMosquitto is part of the Eclipse Foundation, and is an iot.eclipse.org project. The development is driven by Cedalo." # software description - OPTIONAL (but strongly recommended!)
URL="https://mosquitto.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSEPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="mosquitto" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="mosquitto" # apt package name, if applicable
@ -139,6 +140,9 @@ while getopts ":h$options" opt; do
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;

View file

@ -32,6 +32,7 @@ Arguments:
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service name
-L Get install location
-P Get package name
-C Get Conflicts
@ -54,7 +55,7 @@ name="Mosquitto MQTT Client" # software name
author="Eclipse Foundation" # software author - OPTIONAL
description="Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.\n\nThe MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.\n\nThe Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.\n\nMosquitto is part of the Eclipse Foundation, and is an iot.eclipse.org project. The development is driven by Cedalo." # software description - OPTIONAL (but strongly recommended!)
URL="https://mosquitto.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSEPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -137,6 +138,9 @@ while getopts ":h$options" opt; do
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;

View file

@ -33,6 +33,7 @@ Arguments:
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service name
-L Get install location
-P Get package name
-C Get Conflicts
@ -54,7 +55,7 @@ name="name" # software name
author="author" # software author - OPTIONAL
description="description" # software description - OPTIONAL (but strongly recommended!)
URL="URL" # software URL. Can contain multiple URLs - OPTIONAL
options="hxiuagedsrlNADUOSLPCI" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
options="hxiuagedsrlNADUOSELPCI" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="/opt/package/run.sh" # command to launch software, if applicable
service_name="service_name" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="apt_package" # apt package name, if applicable. Can be multiple packages separated by spaces, but if at least one is installed the package will show as "installed" even if the others aren't
@ -148,6 +149,9 @@ while getopts ":$options" opt; do
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;

View file

@ -33,6 +33,7 @@ Arguments:
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service nam
-L Get install location
-P Get package name
-C Get Conflicts
@ -57,7 +58,7 @@ name="Samba File Sharing" # software name
author="Software Freedom Conservancy" # software author - OPTIONAL
description="Femtofox comes with Samba preinstalled but disabled. $init_instructions\n\n$user_message" # software description - OPTIONAL (but strongly recommended!)
URL="https://www.samba.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuagedsrNADUOSPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiuagedsrNADUOSEPCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="smbd nmbd" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -157,6 +158,9 @@ while getopts ":h$options" opt; do
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;

View file

@ -32,6 +32,7 @@ Arguments:
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service nam
-L Get Install location
-C Get Conflicts
-I Check if installed. Returns an error if not installed
@ -53,7 +54,7 @@ name="TC²-BBS" # software name
author="The Comms Channel" # software author - OPTIONAL
description="The TC²-BBS system integrates with Meshtastic devices. The system allows for message handling, bulletin boards, mail systems, and a channel directory." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/TheCommsChannel/TC2-BBS-mesh" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSELCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="python /opt/TC2-BBS-mesh/server.py" # command to launch software, if applicable
service_name="mesh-bbs" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/TC2-BBS-mesh" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -162,6 +163,9 @@ while getopts ":h$options" opt; do
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)

View file

@ -0,0 +1,193 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-E Get service name
-L Get install location
-P Get package name
-C Get Conflicts
-I Check if installed. Returns an error if not installed
Custom for this package:
-k Generate/overwrite ttyd encryption keys
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
name="ttyd Web Terminal" # software name
author="Shuanglei Tao" # software author - OPTIONAL
description="ttyd is a simple command-line tool for sharing terminal over the web.\n\nWhen running, ttyd is available at https://$(hostname).local:7681\nttyd is installed and enabled by default on Foxbuntu.\n\nSSL encryption is provided by keys generated during first-boot or during installation. Your browser may give a warning (net::ERR_CERT_AUTHORITY_INVALID) about the self-signed encryption certificate. This is normal. In Chromium (Chrome, Edge) click \"Advanced\" and \"Continue to femtofox.local (unsafe)\"" # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/tsl0922/ttyd" # software URL. Can contain multiple URLs - OPTIONAL
options="hxiugedsrNADUOSELCIk" # script options in use by software package. For example, for a package with no service, exclude `edsrS`
launch="" # command to launch software, if applicable
service_name="ttyd" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="" # apt package name, if applicable. Can be multiple packages separated by spaces, but if at least one is installed the package will show as "installed" even if the others aren't
location="/opt/ttyd" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
mkdir $location
if ! wget -P "$location/" https://raw.githubusercontent.com/tsl0922/ttyd/refs/heads/main/LICENSE; then # we are required by ttyd to download and store the license
echo "user_message: Download failed. Is internet connected?"
exit 1
fi
if ! wget -qO- https://api.github.com/repos/tsl0922/ttyd/releases/latest | grep "browser_download_url" | grep "armhf" | cut -d '"' -f 4 | xargs wget -O $location/ttyd; then
echo "user_message: Download failed. Is internet connected?"
exit 1
fi
chmod +x /opt/ttyd/ttyd
echo "Generating SSL keys..."
generate_keys
systemctl enable ttyd
systemctl start ttyd
echo "user_message: ttyd service started and should be available at https://$(hostname).local:7681"
exit 0 # should be `exit 1` if operation failed
}
# uninstall script
uninstall() {
systemctl disable ttyd
systemctl stop ttyd
rm -rf $location
echo "user_message: Binary removed. Service has been disabled but service file retained. SSL encryption keys have been retained."
exit 0 # should be `exit 1` if operation failed
}
# code that must be run to initialize the installation prior to use, but can only be run from terminal
interactive_init() {
exit 0 # should be `exit 1` if operation failed
}
# upgrade script
upgrade() {
systemctl stop ttyd
if ! wget -qO- https://api.github.com/repos/tsl0922/ttyd/releases/latest | grep "browser_download_url" | grep "armhf" | cut -d '"' -f 4 | xargs wget -O $location/ttyd; then
echo "user_message: Download failed. Is internet connected?"
exit 1
fi
systemctl start ttyd
echo "user_message: New binary downloaded and service restarted."
exit 0 # should be `exit 1` if operation failed
}
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
# the following works for cloned repos, but not for apt installs
if [ -d "$location" ]; then
exit 0
else
exit 1
fi
}
# custom for this package
generate_keys() {
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout /etc/ssl/private/ttyd.key -out /etc/ssl/certs/ttyd.crt -subj "/CN=$(hostname)" -addext "subjectAltName=DNS:$(hostname)"
chmod 600 /etc/ssl/private/ttyd.key
chmod 644 /etc/ssl/certs/ttyd.crt
if systemctl is-enabled ttyd &>/dev/null; then # if service is enabled
systemctl restart ttyd
fi
}
while getopts ":$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interaction="false"
;;
i) # Option -i (install)
install
;;
u) # Option -u (uninstall)
uninstall
;;
a) # Option -a (interactive initialization)
interactive_init
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
E) # Option -E (Get service name)
echo $service_name
;;
L) echo -e $location ;;
P) echo -e $package_name ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
k) # Option -k (Regenerate SSL keys)
generate_keys
;;
esac
done
exit 0