cdcd89b5b2
- add `tools/welcome-message.sh` with view, set, and reset actions - register `lxs tool welcome|motd` command in `lxs.sh` - add option 7 to interactive tools menu in `tools/index.sh` - document `lxs tool welcome` in README
204 lines
6.6 KiB
Bash
Executable File
204 lines
6.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# LXS - Welcome message (MOTD)
|
|
# Description: View, edit, or reset the SSH login welcome message (/etc/motd)
|
|
# Author: LXS
|
|
# Date: 2025
|
|
|
|
# Load LXS common library (colors, separator, run_spinner, loggers, helpers)
|
|
LXS_RAW_BASE="${LXS_RAW_BASE:-https://git.hyko.cx/hykocx/lxs/raw/branch/main}"
|
|
_lib=$(curl -fsSL "${LXS_RAW_BASE}/lib/common.sh") || { echo "Failed to fetch lib/common.sh" >&2; exit 1; }
|
|
eval "$_lib"
|
|
unset _lib
|
|
export LXS_LOG_FILE="/tmp/lxs_welcome_message.log"
|
|
|
|
require_root "$0" "$@"
|
|
|
|
set -u
|
|
|
|
MOTD_FILE="/etc/motd"
|
|
BACKUP_FILE="/etc/motd.lxs.bak"
|
|
DYNAMIC_DIR="/etc/update-motd.d"
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Arguments
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
ACTION=""
|
|
TEXT=""
|
|
FROM_FILE=""
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
view|--view|show|--show) ACTION="view" ;;
|
|
set|--set|edit|--edit) ACTION="set" ;;
|
|
reset|--reset) ACTION="reset" ;;
|
|
--text) shift; TEXT=${1:-} ;;
|
|
--text=*) TEXT="${1#*=}" ;;
|
|
--from-file) shift; FROM_FILE=${1:-} ;;
|
|
--from-file=*) FROM_FILE="${1#*=}" ;;
|
|
-h|--help)
|
|
cat <<EOF
|
|
Usage: welcome-message.sh [action] [options]
|
|
|
|
Actions:
|
|
view Show the current welcome message
|
|
set Set a new welcome message (see source options below)
|
|
reset Clear the welcome message (a backup is kept)
|
|
|
|
Source options for 'set' (mutually exclusive):
|
|
--text "..." Use the given string as the new message
|
|
--from-file PATH Read the new message from PATH
|
|
(none) Open an interactive editor (\$EDITOR or nano/vi)
|
|
|
|
-h, --help Show this help
|
|
|
|
With no action, an interactive menu is shown.
|
|
|
|
The welcome message lives in ${MOTD_FILE}.
|
|
On Ubuntu, dynamic MOTD scripts in ${DYNAMIC_DIR} also contribute to the
|
|
banner shown at login — those are not modified by this tool.
|
|
EOF
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Unknown option: $1${NC}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -n "$TEXT" ] && [ -n "$FROM_FILE" ]; then
|
|
err "--text and --from-file are mutually exclusive"
|
|
exit 1
|
|
fi
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Helpers
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
view_motd() {
|
|
echo -e "${WHITE}${BOLD}Current welcome message${NC} ${GRAY}(${MOTD_FILE})${NC}"
|
|
show_separator
|
|
if [ ! -s "$MOTD_FILE" ]; then
|
|
echo -e "${GRAY}(empty)${NC}"
|
|
else
|
|
cat "$MOTD_FILE"
|
|
fi
|
|
show_separator
|
|
|
|
if [ -d "$DYNAMIC_DIR" ] && compgen -G "${DYNAMIC_DIR}/*" >/dev/null; then
|
|
echo ""
|
|
warn "Dynamic MOTD scripts are present in ${DYNAMIC_DIR}:"
|
|
find "$DYNAMIC_DIR" -maxdepth 1 -type f -executable -printf ' • %f\n' | sort
|
|
echo -e "${GRAY}These run at login and add to the banner.${NC}"
|
|
fi
|
|
}
|
|
|
|
backup_motd() {
|
|
[ -f "$MOTD_FILE" ] || return 0
|
|
cp -a "$MOTD_FILE" "$BACKUP_FILE"
|
|
info "Previous message backed up to ${BACKUP_FILE}"
|
|
}
|
|
|
|
write_motd() {
|
|
local src=$1
|
|
backup_motd
|
|
install -m 644 "$src" "$MOTD_FILE"
|
|
ok "Welcome message updated"
|
|
echo ""
|
|
view_motd
|
|
}
|
|
|
|
set_from_text() {
|
|
local tmp
|
|
tmp=$(mktemp /tmp/lxs.motd.XXXXXX) || { err "mktemp failed"; return 1; }
|
|
# Preserve embedded newlines; ensure a trailing newline.
|
|
printf '%s\n' "$1" > "$tmp"
|
|
write_motd "$tmp"
|
|
rm -f "$tmp"
|
|
}
|
|
|
|
set_from_file() {
|
|
local src=$1
|
|
if [ ! -r "$src" ]; then
|
|
err "Cannot read file: ${src}"
|
|
return 1
|
|
fi
|
|
write_motd "$src"
|
|
}
|
|
|
|
set_interactive() {
|
|
local editor=${EDITOR:-}
|
|
if [ -z "$editor" ]; then
|
|
if command -v nano >/dev/null 2>&1; then editor="nano"
|
|
elif command -v vi >/dev/null 2>&1; then editor="vi"
|
|
else
|
|
err "No editor found (\$EDITOR unset; nano/vi missing). Use --text or --from-file."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
local tmp
|
|
tmp=$(mktemp /tmp/lxs.motd.XXXXXX) || { err "mktemp failed"; return 1; }
|
|
[ -s "$MOTD_FILE" ] && cat "$MOTD_FILE" > "$tmp"
|
|
|
|
info "Opening ${editor}... save and exit to apply, leave empty to cancel."
|
|
"$editor" "$tmp"
|
|
|
|
if [ ! -s "$tmp" ]; then
|
|
warn "Empty content — change cancelled."
|
|
rm -f "$tmp"
|
|
return 0
|
|
fi
|
|
|
|
write_motd "$tmp"
|
|
rm -f "$tmp"
|
|
}
|
|
|
|
reset_motd() {
|
|
if [ ! -s "$MOTD_FILE" ]; then
|
|
info "Welcome message is already empty."
|
|
return 0
|
|
fi
|
|
backup_motd
|
|
: > "$MOTD_FILE"
|
|
chmod 644 "$MOTD_FILE"
|
|
ok "Welcome message cleared"
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Menu (when no action is given on the CLI)
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
if [ -z "$ACTION" ]; then
|
|
echo -e "${WHITE}${BOLD}LXS - Welcome message${NC}"
|
|
show_separator
|
|
echo -e " ${CYAN}[1]${NC} View current message"
|
|
echo -e " ${GREEN}[2]${NC} Set a new message"
|
|
echo -e " ${YELLOW}[3]${NC} Reset (clear) the message"
|
|
echo -e " ${RED}[0]${NC} Cancel"
|
|
echo ""
|
|
echo -e -n "${BOLD}Choice [0-3]: ${NC}"
|
|
read -r choice
|
|
case "$choice" in
|
|
1) ACTION="view" ;;
|
|
2) ACTION="set" ;;
|
|
3) ACTION="reset" ;;
|
|
0|"") info "Cancelled."; exit 0 ;;
|
|
*) err "Invalid option."; exit 1 ;;
|
|
esac
|
|
fi
|
|
|
|
case "$ACTION" in
|
|
view) view_motd ;;
|
|
set)
|
|
if [ -n "$TEXT" ]; then set_from_text "$TEXT"
|
|
elif [ -n "$FROM_FILE" ]; then set_from_file "$FROM_FILE"
|
|
else set_interactive
|
|
fi
|
|
;;
|
|
reset) reset_motd ;;
|
|
esac
|